vendor: Update golang.org/x/net/...
This commit is contained in:
parent
6af09c61be
commit
897cca0a82
|
@ -1,7 +1,9 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
||||||
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
|
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
|
||||||
|
|
||||||
|
@ -14,77 +16,28 @@ import (
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
func nop() {}
|
// Do sends an HTTP request with the provided http.Client and returns
|
||||||
|
// an HTTP response.
|
||||||
var (
|
//
|
||||||
testHookContextDoneBeforeHeaders = nop
|
|
||||||
testHookDoReturned = nop
|
|
||||||
testHookDidBodyClose = nop
|
|
||||||
)
|
|
||||||
|
|
||||||
// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
|
|
||||||
// If the client is nil, http.DefaultClient is used.
|
// If the client is nil, http.DefaultClient is used.
|
||||||
// If the context is canceled or times out, ctx.Err() will be returned.
|
//
|
||||||
|
// The provided ctx must be non-nil. If it is canceled or times out,
|
||||||
|
// ctx.Err() will be returned.
|
||||||
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
||||||
if client == nil {
|
if client == nil {
|
||||||
client = http.DefaultClient
|
client = http.DefaultClient
|
||||||
}
|
}
|
||||||
|
resp, err := client.Do(req.WithContext(ctx))
|
||||||
// TODO(djd): Respect any existing value of req.Cancel.
|
// If we got an error, and the context has been canceled,
|
||||||
cancel := make(chan struct{})
|
// the context's error is probably more useful.
|
||||||
req.Cancel = cancel
|
if err != nil {
|
||||||
|
|
||||||
type responseAndError struct {
|
|
||||||
resp *http.Response
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
result := make(chan responseAndError, 1)
|
|
||||||
|
|
||||||
// Make local copies of test hooks closed over by goroutines below.
|
|
||||||
// Prevents data races in tests.
|
|
||||||
testHookDoReturned := testHookDoReturned
|
|
||||||
testHookDidBodyClose := testHookDidBodyClose
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
testHookDoReturned()
|
|
||||||
result <- responseAndError{resp, err}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var resp *http.Response
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
testHookContextDoneBeforeHeaders()
|
|
||||||
close(cancel)
|
|
||||||
// Clean up after the goroutine calling client.Do:
|
|
||||||
go func() {
|
|
||||||
if r := <-result; r.resp != nil {
|
|
||||||
testHookDidBodyClose()
|
|
||||||
r.resp.Body.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil, ctx.Err()
|
|
||||||
case r := <-result:
|
|
||||||
var err error
|
|
||||||
resp, err = r.resp, r.err
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
close(cancel)
|
err = ctx.Err()
|
||||||
case <-c:
|
default:
|
||||||
// The response's Body is closed.
|
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
resp.Body = ¬ifyingReader{resp.Body, c}
|
return resp, err
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get issues a GET request via the Do function.
|
// Get issues a GET request via the Do function.
|
||||||
|
@ -119,28 +72,3 @@ func Post(ctx context.Context, client *http.Client, url string, bodyType string,
|
||||||
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
||||||
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// notifyingReader is an io.ReadCloser that closes the notify channel after
|
|
||||||
// Close is called or a Read fails on the underlying ReadCloser.
|
|
||||||
type notifyingReader struct {
|
|
||||||
io.ReadCloser
|
|
||||||
notify chan<- struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *notifyingReader) Read(p []byte) (int, error) {
|
|
||||||
n, err := r.ReadCloser.Read(p)
|
|
||||||
if err != nil && r.notify != nil {
|
|
||||||
close(r.notify)
|
|
||||||
r.notify = nil
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *notifyingReader) Close() error {
|
|
||||||
err := r.ReadCloser.Close()
|
|
||||||
if r.notify != nil {
|
|
||||||
close(r.notify)
|
|
||||||
r.notify = nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
// Copyright 2015 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.7
|
||||||
|
|
||||||
|
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func nop() {}
|
||||||
|
|
||||||
|
var (
|
||||||
|
testHookContextDoneBeforeHeaders = nop
|
||||||
|
testHookDoReturned = nop
|
||||||
|
testHookDidBodyClose = nop
|
||||||
|
)
|
||||||
|
|
||||||
|
// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
|
||||||
|
// If the client is nil, http.DefaultClient is used.
|
||||||
|
// If the context is canceled or times out, ctx.Err() will be returned.
|
||||||
|
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
||||||
|
if client == nil {
|
||||||
|
client = http.DefaultClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(djd): Respect any existing value of req.Cancel.
|
||||||
|
cancel := make(chan struct{})
|
||||||
|
req.Cancel = cancel
|
||||||
|
|
||||||
|
type responseAndError struct {
|
||||||
|
resp *http.Response
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
result := make(chan responseAndError, 1)
|
||||||
|
|
||||||
|
// Make local copies of test hooks closed over by goroutines below.
|
||||||
|
// Prevents data races in tests.
|
||||||
|
testHookDoReturned := testHookDoReturned
|
||||||
|
testHookDidBodyClose := testHookDidBodyClose
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
testHookDoReturned()
|
||||||
|
result <- responseAndError{resp, err}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var resp *http.Response
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
testHookContextDoneBeforeHeaders()
|
||||||
|
close(cancel)
|
||||||
|
// Clean up after the goroutine calling client.Do:
|
||||||
|
go func() {
|
||||||
|
if r := <-result; r.resp != nil {
|
||||||
|
testHookDidBodyClose()
|
||||||
|
r.resp.Body.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case r := <-result:
|
||||||
|
var err error
|
||||||
|
resp, err = r.resp, r.err
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
close(cancel)
|
||||||
|
case <-c:
|
||||||
|
// The response's Body is closed.
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resp.Body = ¬ifyingReader{resp.Body, c}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get issues a GET request via the Do function.
|
||||||
|
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Do(ctx, client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Head issues a HEAD request via the Do function.
|
||||||
|
func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest("HEAD", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Do(ctx, client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post issues a POST request via the Do function.
|
||||||
|
func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest("POST", url, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", bodyType)
|
||||||
|
return Do(ctx, client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostForm issues a POST request via the Do function.
|
||||||
|
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
||||||
|
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// notifyingReader is an io.ReadCloser that closes the notify channel after
|
||||||
|
// Close is called or a Read fails on the underlying ReadCloser.
|
||||||
|
type notifyingReader struct {
|
||||||
|
io.ReadCloser
|
||||||
|
notify chan<- struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *notifyingReader) Read(p []byte) (int, error) {
|
||||||
|
n, err := r.ReadCloser.Read(p)
|
||||||
|
if err != nil && r.notify != nil {
|
||||||
|
close(r.notify)
|
||||||
|
r.notify = nil
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *notifyingReader) Close() error {
|
||||||
|
err := r.ReadCloser.Close()
|
||||||
|
if r.notify != nil {
|
||||||
|
close(r.notify)
|
||||||
|
r.notify = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2016 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 netreflect implements run-time reflection for the
|
||||||
|
// facilities of net package.
|
||||||
|
package netreflect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errInvalidType = errors.New("invalid type")
|
||||||
|
errOpNoSupport = errors.New("operation not supported")
|
||||||
|
)
|
||||||
|
|
||||||
|
// SocketOf returns the socket descriptor of c.
|
||||||
|
func SocketOf(c net.Conn) (uintptr, error) {
|
||||||
|
switch c.(type) {
|
||||||
|
case *net.TCPConn, *net.UDPConn, *net.IPConn, *net.UnixConn:
|
||||||
|
return socketOf(c)
|
||||||
|
default:
|
||||||
|
return 0, errInvalidType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PacketSocketOf returns the socket descriptor of c.
|
||||||
|
func PacketSocketOf(c net.PacketConn) (uintptr, error) {
|
||||||
|
switch c.(type) {
|
||||||
|
case *net.UDPConn, *net.IPConn, *net.UnixConn:
|
||||||
|
return socketOf(c.(net.Conn))
|
||||||
|
default:
|
||||||
|
return 0, errInvalidType
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||||
|
|
||||||
|
package netreflect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func socketOf(c net.Conn) (uintptr, error) {
|
||||||
|
v := reflect.ValueOf(c)
|
||||||
|
switch e := v.Elem(); e.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
fd := e.FieldByName("conn").FieldByName("fd")
|
||||||
|
switch e := fd.Elem(); e.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
sysfd := e.FieldByName("sysfd")
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return uintptr(sysfd.Uint()), nil
|
||||||
|
}
|
||||||
|
return uintptr(sysfd.Int()), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, errInvalidType
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
|
||||||
|
|
||||||
|
package netreflect
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func socketOf(c net.Conn) (uintptr, error) { return 0, errOpNoSupport }
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||||
|
|
||||||
|
package nettest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func protocolNotSupported(err error) bool {
|
||||||
|
switch err := err.(type) {
|
||||||
|
case syscall.Errno:
|
||||||
|
switch err {
|
||||||
|
case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case *os.SyscallError:
|
||||||
|
switch err := err.Err.(type) {
|
||||||
|
case syscall.Errno:
|
||||||
|
switch err {
|
||||||
|
case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
package nettest
|
||||||
|
|
||||||
|
func protocolNotSupported(err error) bool {
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package nettest
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// IsMulticastCapable reports whether ifi is an IP multicast-capable
|
||||||
|
// network interface. Network must be "ip", "ip4" or "ip6".
|
||||||
|
func IsMulticastCapable(network string, ifi *net.Interface) (net.IP, bool) {
|
||||||
|
switch network {
|
||||||
|
case "ip", "ip4", "ip6":
|
||||||
|
default:
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return hasRoutableIP(network, ifi)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoutedInterface returns a network interface that can route IP
|
||||||
|
// traffic and satisfies flags. It returns nil when an appropriate
|
||||||
|
// network interface is not found. Network must be "ip", "ip4" or
|
||||||
|
// "ip6".
|
||||||
|
func RoutedInterface(network string, flags net.Flags) *net.Interface {
|
||||||
|
switch network {
|
||||||
|
case "ip", "ip4", "ip6":
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, ifi := range ift {
|
||||||
|
if ifi.Flags&flags != flags {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := hasRoutableIP(network, &ifi); !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return &ifi
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasRoutableIP(network string, ifi *net.Interface) (net.IP, bool) {
|
||||||
|
ifat, err := ifi.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
for _, ifa := range ifat {
|
||||||
|
switch ifa := ifa.(type) {
|
||||||
|
case *net.IPAddr:
|
||||||
|
if ip := routableIP(network, ifa.IP); ip != nil {
|
||||||
|
return ip, true
|
||||||
|
}
|
||||||
|
case *net.IPNet:
|
||||||
|
if ip := routableIP(network, ifa.IP); ip != nil {
|
||||||
|
return ip, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func routableIP(network string, ip net.IP) net.IP {
|
||||||
|
if !ip.IsLoopback() && !ip.IsLinkLocalUnicast() && !ip.IsGlobalUnicast() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch network {
|
||||||
|
case "ip4":
|
||||||
|
if ip := ip.To4(); ip != nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
case "ip6":
|
||||||
|
if ip.IsLoopback() { // addressing scope of the loopback address depends on each implementation
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if ip := ip.To16(); ip != nil && ip.To4() == nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if ip := ip.To4(); ip != nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
if ip := ip.To16(); ip != nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2015 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 nettest
|
||||||
|
|
||||||
|
const defaultMaxOpenFiles = 256
|
||||||
|
|
||||||
|
// MaxOpenFiles returns the maximum number of open files for the
|
||||||
|
// caller's process.
|
||||||
|
func MaxOpenFiles() int { return maxOpenFiles() }
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2015 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 nettest
|
||||||
|
|
||||||
|
func maxOpenFiles() int { return defaultMaxOpenFiles }
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package nettest
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func maxOpenFiles() int {
|
||||||
|
var rlim syscall.Rlimit
|
||||||
|
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil {
|
||||||
|
return defaultMaxOpenFiles
|
||||||
|
}
|
||||||
|
return int(rlim.Cur)
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Copyright 2015 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 nettest
|
||||||
|
|
||||||
|
func maxOpenFiles() int { return 4 * defaultMaxOpenFiles /* actually it's 16581375 */ }
|
|
@ -0,0 +1,36 @@
|
||||||
|
// 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 nettest provides utilities for IP testing.
|
||||||
|
package nettest // import "golang.org/x/net/internal/nettest"
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// SupportsIPv4 reports whether the platform supports IPv4 networking
|
||||||
|
// functionality.
|
||||||
|
func SupportsIPv4() bool {
|
||||||
|
ln, err := net.Listen("tcp4", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ln.Close()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// SupportsIPv6 reports whether the platform supports IPv6 networking
|
||||||
|
// functionality.
|
||||||
|
func SupportsIPv6() bool {
|
||||||
|
ln, err := net.Listen("tcp6", "[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ln.Close()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProtocolNotSupported reports whether err is a protocol not
|
||||||
|
// supported error.
|
||||||
|
func ProtocolNotSupported(err error) bool {
|
||||||
|
return protocolNotSupported(err)
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2015 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 nettest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SupportsRawIPSocket reports whether the platform supports raw IP
|
||||||
|
// sockets.
|
||||||
|
func SupportsRawIPSocket() (string, bool) {
|
||||||
|
return fmt.Sprintf("not supported on %s", runtime.GOOS), false
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package nettest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SupportsRawIPSocket reports whether the platform supports raw IP
|
||||||
|
// sockets.
|
||||||
|
func SupportsRawIPSocket() (string, bool) {
|
||||||
|
if os.Getuid() != 0 {
|
||||||
|
return fmt.Sprintf("must be root on %s", runtime.GOOS), false
|
||||||
|
}
|
||||||
|
return "", true
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2015 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 nettest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SupportsRawIPSocket reports whether the platform supports raw IP
|
||||||
|
// sockets.
|
||||||
|
func SupportsRawIPSocket() (string, bool) {
|
||||||
|
// From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
|
||||||
|
// Note: To use a socket of type SOCK_RAW requires administrative privileges.
|
||||||
|
// Users running Winsock applications that use raw sockets must be a member of
|
||||||
|
// the Administrators group on the local computer, otherwise raw socket calls
|
||||||
|
// will fail with an error code of WSAEACCES. On Windows Vista and later, access
|
||||||
|
// for raw sockets is enforced at socket creation. In earlier versions of Windows,
|
||||||
|
// access for raw sockets is enforced during other socket operations.
|
||||||
|
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
|
||||||
|
if err == syscall.WSAEACCES {
|
||||||
|
return fmt.Sprintf("no access to raw socket allowed on %s", runtime.GOOS), false
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err.Error(), false
|
||||||
|
}
|
||||||
|
syscall.Closesocket(s)
|
||||||
|
return "", true
|
||||||
|
}
|
|
@ -0,0 +1,525 @@
|
||||||
|
// Copyright 2015 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 timeseries implements a time series structure for stats collection.
|
||||||
|
package timeseries // import "golang.org/x/net/internal/timeseries"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
timeSeriesNumBuckets = 64
|
||||||
|
minuteHourSeriesNumBuckets = 60
|
||||||
|
)
|
||||||
|
|
||||||
|
var timeSeriesResolutions = []time.Duration{
|
||||||
|
1 * time.Second,
|
||||||
|
10 * time.Second,
|
||||||
|
1 * time.Minute,
|
||||||
|
10 * time.Minute,
|
||||||
|
1 * time.Hour,
|
||||||
|
6 * time.Hour,
|
||||||
|
24 * time.Hour, // 1 day
|
||||||
|
7 * 24 * time.Hour, // 1 week
|
||||||
|
4 * 7 * 24 * time.Hour, // 4 weeks
|
||||||
|
16 * 7 * 24 * time.Hour, // 16 weeks
|
||||||
|
}
|
||||||
|
|
||||||
|
var minuteHourSeriesResolutions = []time.Duration{
|
||||||
|
1 * time.Second,
|
||||||
|
1 * time.Minute,
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Observable is a kind of data that can be aggregated in a time series.
|
||||||
|
type Observable interface {
|
||||||
|
Multiply(ratio float64) // Multiplies the data in self by a given ratio
|
||||||
|
Add(other Observable) // Adds the data from a different observation to self
|
||||||
|
Clear() // Clears the observation so it can be reused.
|
||||||
|
CopyFrom(other Observable) // Copies the contents of a given observation to self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float attaches the methods of Observable to a float64.
|
||||||
|
type Float float64
|
||||||
|
|
||||||
|
// NewFloat returns a Float.
|
||||||
|
func NewFloat() Observable {
|
||||||
|
f := Float(0)
|
||||||
|
return &f
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the float as a string.
|
||||||
|
func (f *Float) String() string { return fmt.Sprintf("%g", f.Value()) }
|
||||||
|
|
||||||
|
// Value returns the float's value.
|
||||||
|
func (f *Float) Value() float64 { return float64(*f) }
|
||||||
|
|
||||||
|
func (f *Float) Multiply(ratio float64) { *f *= Float(ratio) }
|
||||||
|
|
||||||
|
func (f *Float) Add(other Observable) {
|
||||||
|
o := other.(*Float)
|
||||||
|
*f += *o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Float) Clear() { *f = 0 }
|
||||||
|
|
||||||
|
func (f *Float) CopyFrom(other Observable) {
|
||||||
|
o := other.(*Float)
|
||||||
|
*f = *o
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Clock tells the current time.
|
||||||
|
type Clock interface {
|
||||||
|
Time() time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type defaultClock int
|
||||||
|
|
||||||
|
var defaultClockInstance defaultClock
|
||||||
|
|
||||||
|
func (defaultClock) Time() time.Time { return time.Now() }
|
||||||
|
|
||||||
|
// Information kept per level. Each level consists of a circular list of
|
||||||
|
// observations. The start of the level may be derived from end and the
|
||||||
|
// len(buckets) * sizeInMillis.
|
||||||
|
type tsLevel struct {
|
||||||
|
oldest int // index to oldest bucketed Observable
|
||||||
|
newest int // index to newest bucketed Observable
|
||||||
|
end time.Time // end timestamp for this level
|
||||||
|
size time.Duration // duration of the bucketed Observable
|
||||||
|
buckets []Observable // collections of observations
|
||||||
|
provider func() Observable // used for creating new Observable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tsLevel) Clear() {
|
||||||
|
l.oldest = 0
|
||||||
|
l.newest = len(l.buckets) - 1
|
||||||
|
l.end = time.Time{}
|
||||||
|
for i := range l.buckets {
|
||||||
|
if l.buckets[i] != nil {
|
||||||
|
l.buckets[i].Clear()
|
||||||
|
l.buckets[i] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tsLevel) InitLevel(size time.Duration, numBuckets int, f func() Observable) {
|
||||||
|
l.size = size
|
||||||
|
l.provider = f
|
||||||
|
l.buckets = make([]Observable, numBuckets)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keeps a sequence of levels. Each level is responsible for storing data at
|
||||||
|
// a given resolution. For example, the first level stores data at a one
|
||||||
|
// minute resolution while the second level stores data at a one hour
|
||||||
|
// resolution.
|
||||||
|
|
||||||
|
// Each level is represented by a sequence of buckets. Each bucket spans an
|
||||||
|
// interval equal to the resolution of the level. New observations are added
|
||||||
|
// to the last bucket.
|
||||||
|
type timeSeries struct {
|
||||||
|
provider func() Observable // make more Observable
|
||||||
|
numBuckets int // number of buckets in each level
|
||||||
|
levels []*tsLevel // levels of bucketed Observable
|
||||||
|
lastAdd time.Time // time of last Observable tracked
|
||||||
|
total Observable // convenient aggregation of all Observable
|
||||||
|
clock Clock // Clock for getting current time
|
||||||
|
pending Observable // observations not yet bucketed
|
||||||
|
pendingTime time.Time // what time are we keeping in pending
|
||||||
|
dirty bool // if there are pending observations
|
||||||
|
}
|
||||||
|
|
||||||
|
// init initializes a level according to the supplied criteria.
|
||||||
|
func (ts *timeSeries) init(resolutions []time.Duration, f func() Observable, numBuckets int, clock Clock) {
|
||||||
|
ts.provider = f
|
||||||
|
ts.numBuckets = numBuckets
|
||||||
|
ts.clock = clock
|
||||||
|
ts.levels = make([]*tsLevel, len(resolutions))
|
||||||
|
|
||||||
|
for i := range resolutions {
|
||||||
|
if i > 0 && resolutions[i-1] >= resolutions[i] {
|
||||||
|
log.Print("timeseries: resolutions must be monotonically increasing")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
newLevel := new(tsLevel)
|
||||||
|
newLevel.InitLevel(resolutions[i], ts.numBuckets, ts.provider)
|
||||||
|
ts.levels[i] = newLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all observations from the time series.
|
||||||
|
func (ts *timeSeries) Clear() {
|
||||||
|
ts.lastAdd = time.Time{}
|
||||||
|
ts.total = ts.resetObservation(ts.total)
|
||||||
|
ts.pending = ts.resetObservation(ts.pending)
|
||||||
|
ts.pendingTime = time.Time{}
|
||||||
|
ts.dirty = false
|
||||||
|
|
||||||
|
for i := range ts.levels {
|
||||||
|
ts.levels[i].Clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add records an observation at the current time.
|
||||||
|
func (ts *timeSeries) Add(observation Observable) {
|
||||||
|
ts.AddWithTime(observation, ts.clock.Time())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddWithTime records an observation at the specified time.
|
||||||
|
func (ts *timeSeries) AddWithTime(observation Observable, t time.Time) {
|
||||||
|
|
||||||
|
smallBucketDuration := ts.levels[0].size
|
||||||
|
|
||||||
|
if t.After(ts.lastAdd) {
|
||||||
|
ts.lastAdd = t
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.After(ts.pendingTime) {
|
||||||
|
ts.advance(t)
|
||||||
|
ts.mergePendingUpdates()
|
||||||
|
ts.pendingTime = ts.levels[0].end
|
||||||
|
ts.pending.CopyFrom(observation)
|
||||||
|
ts.dirty = true
|
||||||
|
} else if t.After(ts.pendingTime.Add(-1 * smallBucketDuration)) {
|
||||||
|
// The observation is close enough to go into the pending bucket.
|
||||||
|
// This compensates for clock skewing and small scheduling delays
|
||||||
|
// by letting the update stay in the fast path.
|
||||||
|
ts.pending.Add(observation)
|
||||||
|
ts.dirty = true
|
||||||
|
} else {
|
||||||
|
ts.mergeValue(observation, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeValue inserts the observation at the specified time in the past into all levels.
|
||||||
|
func (ts *timeSeries) mergeValue(observation Observable, t time.Time) {
|
||||||
|
for _, level := range ts.levels {
|
||||||
|
index := (ts.numBuckets - 1) - int(level.end.Sub(t)/level.size)
|
||||||
|
if 0 <= index && index < ts.numBuckets {
|
||||||
|
bucketNumber := (level.oldest + index) % ts.numBuckets
|
||||||
|
if level.buckets[bucketNumber] == nil {
|
||||||
|
level.buckets[bucketNumber] = level.provider()
|
||||||
|
}
|
||||||
|
level.buckets[bucketNumber].Add(observation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ts.total.Add(observation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergePendingUpdates applies the pending updates into all levels.
|
||||||
|
func (ts *timeSeries) mergePendingUpdates() {
|
||||||
|
if ts.dirty {
|
||||||
|
ts.mergeValue(ts.pending, ts.pendingTime)
|
||||||
|
ts.pending = ts.resetObservation(ts.pending)
|
||||||
|
ts.dirty = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance cycles the buckets at each level until the latest bucket in
|
||||||
|
// each level can hold the time specified.
|
||||||
|
func (ts *timeSeries) advance(t time.Time) {
|
||||||
|
if !t.After(ts.levels[0].end) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := 0; i < len(ts.levels); i++ {
|
||||||
|
level := ts.levels[i]
|
||||||
|
if !level.end.Before(t) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the time is sufficiently far, just clear the level and advance
|
||||||
|
// directly.
|
||||||
|
if !t.Before(level.end.Add(level.size * time.Duration(ts.numBuckets))) {
|
||||||
|
for _, b := range level.buckets {
|
||||||
|
ts.resetObservation(b)
|
||||||
|
}
|
||||||
|
level.end = time.Unix(0, (t.UnixNano()/level.size.Nanoseconds())*level.size.Nanoseconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
for t.After(level.end) {
|
||||||
|
level.end = level.end.Add(level.size)
|
||||||
|
level.newest = level.oldest
|
||||||
|
level.oldest = (level.oldest + 1) % ts.numBuckets
|
||||||
|
ts.resetObservation(level.buckets[level.newest])
|
||||||
|
}
|
||||||
|
|
||||||
|
t = level.end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Latest returns the sum of the num latest buckets from the level.
|
||||||
|
func (ts *timeSeries) Latest(level, num int) Observable {
|
||||||
|
now := ts.clock.Time()
|
||||||
|
if ts.levels[0].end.Before(now) {
|
||||||
|
ts.advance(now)
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.mergePendingUpdates()
|
||||||
|
|
||||||
|
result := ts.provider()
|
||||||
|
l := ts.levels[level]
|
||||||
|
index := l.newest
|
||||||
|
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
if l.buckets[index] != nil {
|
||||||
|
result.Add(l.buckets[index])
|
||||||
|
}
|
||||||
|
if index == 0 {
|
||||||
|
index = ts.numBuckets
|
||||||
|
}
|
||||||
|
index--
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// LatestBuckets returns a copy of the num latest buckets from level.
|
||||||
|
func (ts *timeSeries) LatestBuckets(level, num int) []Observable {
|
||||||
|
if level < 0 || level > len(ts.levels) {
|
||||||
|
log.Print("timeseries: bad level argument: ", level)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if num < 0 || num >= ts.numBuckets {
|
||||||
|
log.Print("timeseries: bad num argument: ", num)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
results := make([]Observable, num)
|
||||||
|
now := ts.clock.Time()
|
||||||
|
if ts.levels[0].end.Before(now) {
|
||||||
|
ts.advance(now)
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.mergePendingUpdates()
|
||||||
|
|
||||||
|
l := ts.levels[level]
|
||||||
|
index := l.newest
|
||||||
|
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
result := ts.provider()
|
||||||
|
results[i] = result
|
||||||
|
if l.buckets[index] != nil {
|
||||||
|
result.CopyFrom(l.buckets[index])
|
||||||
|
}
|
||||||
|
|
||||||
|
if index == 0 {
|
||||||
|
index = ts.numBuckets
|
||||||
|
}
|
||||||
|
index -= 1
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScaleBy updates observations by scaling by factor.
|
||||||
|
func (ts *timeSeries) ScaleBy(factor float64) {
|
||||||
|
for _, l := range ts.levels {
|
||||||
|
for i := 0; i < ts.numBuckets; i++ {
|
||||||
|
l.buckets[i].Multiply(factor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.total.Multiply(factor)
|
||||||
|
ts.pending.Multiply(factor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range returns the sum of observations added over the specified time range.
|
||||||
|
// If start or finish times don't fall on bucket boundaries of the same
|
||||||
|
// level, then return values are approximate answers.
|
||||||
|
func (ts *timeSeries) Range(start, finish time.Time) Observable {
|
||||||
|
return ts.ComputeRange(start, finish, 1)[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recent returns the sum of observations from the last delta.
|
||||||
|
func (ts *timeSeries) Recent(delta time.Duration) Observable {
|
||||||
|
now := ts.clock.Time()
|
||||||
|
return ts.Range(now.Add(-delta), now)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total returns the total of all observations.
|
||||||
|
func (ts *timeSeries) Total() Observable {
|
||||||
|
ts.mergePendingUpdates()
|
||||||
|
return ts.total
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComputeRange computes a specified number of values into a slice using
|
||||||
|
// the observations recorded over the specified time period. The return
|
||||||
|
// values are approximate if the start or finish times don't fall on the
|
||||||
|
// bucket boundaries at the same level or if the number of buckets spanning
|
||||||
|
// the range is not an integral multiple of num.
|
||||||
|
func (ts *timeSeries) ComputeRange(start, finish time.Time, num int) []Observable {
|
||||||
|
if start.After(finish) {
|
||||||
|
log.Printf("timeseries: start > finish, %v>%v", start, finish)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if num < 0 {
|
||||||
|
log.Printf("timeseries: num < 0, %v", num)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
results := make([]Observable, num)
|
||||||
|
|
||||||
|
for _, l := range ts.levels {
|
||||||
|
if !start.Before(l.end.Add(-l.size * time.Duration(ts.numBuckets))) {
|
||||||
|
ts.extract(l, start, finish, num, results)
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failed to find a level that covers the desired range. So just
|
||||||
|
// extract from the last level, even if it doesn't cover the entire
|
||||||
|
// desired range.
|
||||||
|
ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results)
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecentList returns the specified number of values in slice over the most
|
||||||
|
// recent time period of the specified range.
|
||||||
|
func (ts *timeSeries) RecentList(delta time.Duration, num int) []Observable {
|
||||||
|
if delta < 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
now := ts.clock.Time()
|
||||||
|
return ts.ComputeRange(now.Add(-delta), now, num)
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract returns a slice of specified number of observations from a given
|
||||||
|
// level over a given range.
|
||||||
|
func (ts *timeSeries) extract(l *tsLevel, start, finish time.Time, num int, results []Observable) {
|
||||||
|
ts.mergePendingUpdates()
|
||||||
|
|
||||||
|
srcInterval := l.size
|
||||||
|
dstInterval := finish.Sub(start) / time.Duration(num)
|
||||||
|
dstStart := start
|
||||||
|
srcStart := l.end.Add(-srcInterval * time.Duration(ts.numBuckets))
|
||||||
|
|
||||||
|
srcIndex := 0
|
||||||
|
|
||||||
|
// Where should scanning start?
|
||||||
|
if dstStart.After(srcStart) {
|
||||||
|
advance := dstStart.Sub(srcStart) / srcInterval
|
||||||
|
srcIndex += int(advance)
|
||||||
|
srcStart = srcStart.Add(advance * srcInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The i'th value is computed as show below.
|
||||||
|
// interval = (finish/start)/num
|
||||||
|
// i'th value = sum of observation in range
|
||||||
|
// [ start + i * interval,
|
||||||
|
// start + (i + 1) * interval )
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
results[i] = ts.resetObservation(results[i])
|
||||||
|
dstEnd := dstStart.Add(dstInterval)
|
||||||
|
for srcIndex < ts.numBuckets && srcStart.Before(dstEnd) {
|
||||||
|
srcEnd := srcStart.Add(srcInterval)
|
||||||
|
if srcEnd.After(ts.lastAdd) {
|
||||||
|
srcEnd = ts.lastAdd
|
||||||
|
}
|
||||||
|
|
||||||
|
if !srcEnd.Before(dstStart) {
|
||||||
|
srcValue := l.buckets[(srcIndex+l.oldest)%ts.numBuckets]
|
||||||
|
if !srcStart.Before(dstStart) && !srcEnd.After(dstEnd) {
|
||||||
|
// dst completely contains src.
|
||||||
|
if srcValue != nil {
|
||||||
|
results[i].Add(srcValue)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// dst partially overlaps src.
|
||||||
|
overlapStart := maxTime(srcStart, dstStart)
|
||||||
|
overlapEnd := minTime(srcEnd, dstEnd)
|
||||||
|
base := srcEnd.Sub(srcStart)
|
||||||
|
fraction := overlapEnd.Sub(overlapStart).Seconds() / base.Seconds()
|
||||||
|
|
||||||
|
used := ts.provider()
|
||||||
|
if srcValue != nil {
|
||||||
|
used.CopyFrom(srcValue)
|
||||||
|
}
|
||||||
|
used.Multiply(fraction)
|
||||||
|
results[i].Add(used)
|
||||||
|
}
|
||||||
|
|
||||||
|
if srcEnd.After(dstEnd) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
srcIndex++
|
||||||
|
srcStart = srcStart.Add(srcInterval)
|
||||||
|
}
|
||||||
|
dstStart = dstStart.Add(dstInterval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resetObservation clears the content so the struct may be reused.
|
||||||
|
func (ts *timeSeries) resetObservation(observation Observable) Observable {
|
||||||
|
if observation == nil {
|
||||||
|
observation = ts.provider()
|
||||||
|
} else {
|
||||||
|
observation.Clear()
|
||||||
|
}
|
||||||
|
return observation
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeSeries tracks data at granularities from 1 second to 16 weeks.
|
||||||
|
type TimeSeries struct {
|
||||||
|
timeSeries
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTimeSeries creates a new TimeSeries using the function provided for creating new Observable.
|
||||||
|
func NewTimeSeries(f func() Observable) *TimeSeries {
|
||||||
|
return NewTimeSeriesWithClock(f, defaultClockInstance)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTimeSeriesWithClock creates a new TimeSeries using the function provided for creating new Observable and the clock for
|
||||||
|
// assigning timestamps.
|
||||||
|
func NewTimeSeriesWithClock(f func() Observable, clock Clock) *TimeSeries {
|
||||||
|
ts := new(TimeSeries)
|
||||||
|
ts.timeSeries.init(timeSeriesResolutions, f, timeSeriesNumBuckets, clock)
|
||||||
|
return ts
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinuteHourSeries tracks data at granularities of 1 minute and 1 hour.
|
||||||
|
type MinuteHourSeries struct {
|
||||||
|
timeSeries
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMinuteHourSeries creates a new MinuteHourSeries using the function provided for creating new Observable.
|
||||||
|
func NewMinuteHourSeries(f func() Observable) *MinuteHourSeries {
|
||||||
|
return NewMinuteHourSeriesWithClock(f, defaultClockInstance)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMinuteHourSeriesWithClock creates a new MinuteHourSeries using the function provided for creating new Observable and the clock for
|
||||||
|
// assigning timestamps.
|
||||||
|
func NewMinuteHourSeriesWithClock(f func() Observable, clock Clock) *MinuteHourSeries {
|
||||||
|
ts := new(MinuteHourSeries)
|
||||||
|
ts.timeSeries.init(minuteHourSeriesResolutions, f,
|
||||||
|
minuteHourSeriesNumBuckets, clock)
|
||||||
|
return ts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *MinuteHourSeries) Minute() Observable {
|
||||||
|
return ts.timeSeries.Latest(0, 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *MinuteHourSeries) Hour() Observable {
|
||||||
|
return ts.timeSeries.Latest(1, 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
func minTime(a, b time.Time) time.Time {
|
||||||
|
if a.Before(b) {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func maxTime(a, b time.Time) time.Time {
|
||||||
|
if a.After(b) {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Copyright 2016 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"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBPF(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := net.ListenPacket("udp6", "[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer l.Close()
|
||||||
|
|
||||||
|
p := ipv6.NewPacketConn(l)
|
||||||
|
|
||||||
|
// This filter accepts UDP packets whose first payload byte is
|
||||||
|
// even.
|
||||||
|
prog, err := bpf.Assemble([]bpf.Instruction{
|
||||||
|
// Load the first byte of the payload (skipping UDP header).
|
||||||
|
bpf.LoadAbsolute{Off: 8, Size: 1},
|
||||||
|
// Select LSB of the byte.
|
||||||
|
bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
|
||||||
|
// Byte is even?
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
|
||||||
|
// Accept.
|
||||||
|
bpf.RetConstant{Val: 4096},
|
||||||
|
// Ignore.
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("compiling BPF: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.SetBPF(prog); err != nil {
|
||||||
|
t.Fatalf("attaching filter to Conn: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := net.Dial("udp6", l.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer s.Close()
|
||||||
|
go func() {
|
||||||
|
for i := byte(0); i < 10; i++ {
|
||||||
|
s.Write([]byte{i})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
l.SetDeadline(time.Now().Add(2 * time.Second))
|
||||||
|
seen := make([]bool, 5)
|
||||||
|
for {
|
||||||
|
var b [512]byte
|
||||||
|
n, _, err := l.ReadFrom(b[:])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("reading from listener: %s", err)
|
||||||
|
}
|
||||||
|
if n != 1 {
|
||||||
|
t.Fatalf("unexpected packet length, want 1, got %d", n)
|
||||||
|
}
|
||||||
|
if b[0] >= 10 {
|
||||||
|
t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
|
||||||
|
}
|
||||||
|
if b[0]%2 != 0 {
|
||||||
|
t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
|
||||||
|
}
|
||||||
|
seen[b[0]/2] = true
|
||||||
|
|
||||||
|
seenAll := true
|
||||||
|
for _, v := range seen {
|
||||||
|
if !v {
|
||||||
|
seenAll = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if seenAll {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
"golang.org/x/net/internal/netreflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetBPF attaches a BPF program to the connection.
|
||||||
|
//
|
||||||
|
// Only supported on Linux.
|
||||||
|
func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
|
||||||
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prog := sysSockFProg{
|
||||||
|
Len: uint16(len(filter)),
|
||||||
|
Filter: (*sysSockFilter)(unsafe.Pointer(&filter[0])),
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(s, sysSOL_SOCKET, sysSO_ATTACH_FILTER, unsafe.Pointer(&prog), uint32(unsafe.Sizeof(prog))))
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2016 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 !linux
|
||||||
|
|
||||||
|
package ipv6
|
||||||
|
|
||||||
|
import "golang.org/x/net/bpf"
|
||||||
|
|
||||||
|
// SetBPF attaches a BPF program to the connection.
|
||||||
|
//
|
||||||
|
// Only supported on Linux.
|
||||||
|
func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
package ipv6
|
package ipv6
|
||||||
|
|
||||||
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@ import (
|
||||||
"golang.org/x/net/internal/iana"
|
"golang.org/x/net/internal/iana"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
opt.Lock()
|
opt.Lock()
|
||||||
defer opt.Unlock()
|
defer opt.Unlock()
|
||||||
if cf&FlagTrafficClass != 0 && sockOpts[ssoReceiveTrafficClass].name > 0 {
|
if cf&FlagTrafficClass != 0 && sockOpts[ssoReceiveTrafficClass].name > 0 {
|
||||||
if err := setInt(fd, &sockOpts[ssoReceiveTrafficClass], boolint(on)); err != nil {
|
if err := setInt(s, &sockOpts[ssoReceiveTrafficClass], boolint(on)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if on {
|
if on {
|
||||||
|
@ -27,7 +27,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cf&FlagHopLimit != 0 && sockOpts[ssoReceiveHopLimit].name > 0 {
|
if cf&FlagHopLimit != 0 && sockOpts[ssoReceiveHopLimit].name > 0 {
|
||||||
if err := setInt(fd, &sockOpts[ssoReceiveHopLimit], boolint(on)); err != nil {
|
if err := setInt(s, &sockOpts[ssoReceiveHopLimit], boolint(on)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if on {
|
if on {
|
||||||
|
@ -37,7 +37,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cf&flagPacketInfo != 0 && sockOpts[ssoReceivePacketInfo].name > 0 {
|
if cf&flagPacketInfo != 0 && sockOpts[ssoReceivePacketInfo].name > 0 {
|
||||||
if err := setInt(fd, &sockOpts[ssoReceivePacketInfo], boolint(on)); err != nil {
|
if err := setInt(s, &sockOpts[ssoReceivePacketInfo], boolint(on)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if on {
|
if on {
|
||||||
|
@ -47,7 +47,7 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cf&FlagPathMTU != 0 && sockOpts[ssoReceivePathMTU].name > 0 {
|
if cf&FlagPathMTU != 0 && sockOpts[ssoReceivePathMTU].name > 0 {
|
||||||
if err := setInt(fd, &sockOpts[ssoReceivePathMTU], boolint(on)); err != nil {
|
if err := setInt(s, &sockOpts[ssoReceivePathMTU], boolint(on)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if on {
|
if on {
|
||||||
|
|
|
@ -6,7 +6,7 @@ package ipv6
|
||||||
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
func setControlMessage(fd syscall.Handle, opt *rawOpt, cf ControlFlags, on bool) error {
|
func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
// TODO(mikio): implement this
|
// TODO(mikio): implement this
|
||||||
return syscall.EWINDOWS
|
return syscall.EWINDOWS
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ package ipv6
|
||||||
#include <linux/in6.h>
|
#include <linux/in6.h>
|
||||||
#include <linux/ipv6.h>
|
#include <linux/ipv6.h>
|
||||||
#include <linux/icmpv6.h>
|
#include <linux/icmpv6.h>
|
||||||
|
#include <linux/filter.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
@ -104,6 +106,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = C.ICMPV6_FILTER_BLOCKOTHERS
|
sysICMPV6_FILTER_BLOCKOTHERS = C.ICMPV6_FILTER_BLOCKOTHERS
|
||||||
sysICMPV6_FILTER_PASSONLY = C.ICMPV6_FILTER_PASSONLY
|
sysICMPV6_FILTER_PASSONLY = C.ICMPV6_FILTER_PASSONLY
|
||||||
|
|
||||||
|
sysSOL_SOCKET = C.SOL_SOCKET
|
||||||
|
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
sysSizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
||||||
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
sysSizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
sysSizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||||
|
@ -134,3 +139,7 @@ type sysGroupReq C.struct_group_req
|
||||||
type sysGroupSourceReq C.struct_group_source_req
|
type sysGroupSourceReq C.struct_group_source_req
|
||||||
|
|
||||||
type sysICMPv6Filter C.struct_icmp6_filter
|
type sysICMPv6Filter C.struct_icmp6_filter
|
||||||
|
|
||||||
|
type sysSockFProg C.struct_sock_fprog
|
||||||
|
|
||||||
|
type sysSockFilter C.struct_sock_filter
|
||||||
|
|
|
@ -9,6 +9,8 @@ package ipv6
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/netreflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MulticastHopLimit returns the hop limit field value for outgoing
|
// MulticastHopLimit returns the hop limit field value for outgoing
|
||||||
|
@ -17,11 +19,11 @@ func (c *dgramOpt) MulticastHopLimit() (int, error) {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return 0, syscall.EINVAL
|
return 0, syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return getInt(fd, &sockOpts[ssoMulticastHopLimit])
|
return getInt(s, &sockOpts[ssoMulticastHopLimit])
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMulticastHopLimit sets the hop limit field value for future
|
// SetMulticastHopLimit sets the hop limit field value for future
|
||||||
|
@ -30,11 +32,11 @@ func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setInt(fd, &sockOpts[ssoMulticastHopLimit], hoplim)
|
return setInt(s, &sockOpts[ssoMulticastHopLimit], hoplim)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MulticastInterface returns the default interface for multicast
|
// MulticastInterface returns the default interface for multicast
|
||||||
|
@ -43,11 +45,11 @@ func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return nil, syscall.EINVAL
|
return nil, syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return getInterface(fd, &sockOpts[ssoMulticastInterface])
|
return getInterface(s, &sockOpts[ssoMulticastInterface])
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMulticastInterface sets the default interface for future
|
// SetMulticastInterface sets the default interface for future
|
||||||
|
@ -56,11 +58,11 @@ func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setInterface(fd, &sockOpts[ssoMulticastInterface], ifi)
|
return setInterface(s, &sockOpts[ssoMulticastInterface], ifi)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MulticastLoopback reports whether transmitted multicast packets
|
// MulticastLoopback reports whether transmitted multicast packets
|
||||||
|
@ -69,11 +71,11 @@ func (c *dgramOpt) MulticastLoopback() (bool, error) {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return false, syscall.EINVAL
|
return false, syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
on, err := getInt(fd, &sockOpts[ssoMulticastLoopback])
|
on, err := getInt(s, &sockOpts[ssoMulticastLoopback])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -86,11 +88,11 @@ func (c *dgramOpt) SetMulticastLoopback(on bool) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setInt(fd, &sockOpts[ssoMulticastLoopback], boolint(on))
|
return setInt(s, &sockOpts[ssoMulticastLoopback], boolint(on))
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinGroup joins the group address group on the interface ifi.
|
// JoinGroup joins the group address group on the interface ifi.
|
||||||
|
@ -106,7 +108,7 @@ func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -114,7 +116,7 @@ func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
|
||||||
if grp == nil {
|
if grp == nil {
|
||||||
return errMissingAddress
|
return errMissingAddress
|
||||||
}
|
}
|
||||||
return setGroup(fd, &sockOpts[ssoJoinGroup], ifi, grp)
|
return setGroup(s, &sockOpts[ssoJoinGroup], ifi, grp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeaveGroup leaves the group address group on the interface ifi
|
// LeaveGroup leaves the group address group on the interface ifi
|
||||||
|
@ -124,7 +126,7 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -132,7 +134,7 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
|
||||||
if grp == nil {
|
if grp == nil {
|
||||||
return errMissingAddress
|
return errMissingAddress
|
||||||
}
|
}
|
||||||
return setGroup(fd, &sockOpts[ssoLeaveGroup], ifi, grp)
|
return setGroup(s, &sockOpts[ssoLeaveGroup], ifi, grp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinSourceSpecificGroup joins the source-specific group comprising
|
// JoinSourceSpecificGroup joins the source-specific group comprising
|
||||||
|
@ -145,7 +147,7 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -157,7 +159,7 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return errMissingAddress
|
return errMissingAddress
|
||||||
}
|
}
|
||||||
return setSourceGroup(fd, &sockOpts[ssoJoinSourceGroup], ifi, grp, src)
|
return setSourceGroup(s, &sockOpts[ssoJoinSourceGroup], ifi, grp, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeaveSourceSpecificGroup leaves the source-specific group on the
|
// LeaveSourceSpecificGroup leaves the source-specific group on the
|
||||||
|
@ -166,7 +168,7 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -178,7 +180,7 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return errMissingAddress
|
return errMissingAddress
|
||||||
}
|
}
|
||||||
return setSourceGroup(fd, &sockOpts[ssoLeaveSourceGroup], ifi, grp, src)
|
return setSourceGroup(s, &sockOpts[ssoLeaveSourceGroup], ifi, grp, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExcludeSourceSpecificGroup excludes the source-specific group from
|
// ExcludeSourceSpecificGroup excludes the source-specific group from
|
||||||
|
@ -188,7 +190,7 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -200,7 +202,7 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return errMissingAddress
|
return errMissingAddress
|
||||||
}
|
}
|
||||||
return setSourceGroup(fd, &sockOpts[ssoBlockSourceGroup], ifi, grp, src)
|
return setSourceGroup(s, &sockOpts[ssoBlockSourceGroup], ifi, grp, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncludeSourceSpecificGroup includes the excluded source-specific
|
// IncludeSourceSpecificGroup includes the excluded source-specific
|
||||||
|
@ -209,7 +211,7 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -221,7 +223,7 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return errMissingAddress
|
return errMissingAddress
|
||||||
}
|
}
|
||||||
return setSourceGroup(fd, &sockOpts[ssoUnblockSourceGroup], ifi, grp, src)
|
return setSourceGroup(s, &sockOpts[ssoUnblockSourceGroup], ifi, grp, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checksum reports whether the kernel will compute, store or verify a
|
// Checksum reports whether the kernel will compute, store or verify a
|
||||||
|
@ -232,11 +234,11 @@ func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return false, 0, syscall.EINVAL
|
return false, 0, syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, 0, err
|
return false, 0, err
|
||||||
}
|
}
|
||||||
offset, err = getInt(fd, &sockOpts[ssoChecksum])
|
offset, err = getInt(s, &sockOpts[ssoChecksum])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, 0, err
|
return false, 0, err
|
||||||
}
|
}
|
||||||
|
@ -253,14 +255,14 @@ func (c *dgramOpt) SetChecksum(on bool, offset int) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !on {
|
if !on {
|
||||||
offset = -1
|
offset = -1
|
||||||
}
|
}
|
||||||
return setInt(fd, &sockOpts[ssoChecksum], offset)
|
return setInt(s, &sockOpts[ssoChecksum], offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ICMPFilter returns an ICMP filter.
|
// ICMPFilter returns an ICMP filter.
|
||||||
|
@ -268,11 +270,11 @@ func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return nil, syscall.EINVAL
|
return nil, syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return getICMPFilter(fd, &sockOpts[ssoICMPFilter])
|
return getICMPFilter(s, &sockOpts[ssoICMPFilter])
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetICMPFilter deploys the ICMP filter.
|
// SetICMPFilter deploys the ICMP filter.
|
||||||
|
@ -280,9 +282,9 @@ func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.PacketSocketOf(c.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setICMPFilter(fd, &sockOpts[ssoICMPFilter], f)
|
return setICMPFilter(s, &sockOpts[ssoICMPFilter], f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/netreflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Conn represents a network endpoint that uses IPv6 transport.
|
// A Conn represents a network endpoint that uses IPv6 transport.
|
||||||
|
@ -29,11 +31,11 @@ func (c *Conn) PathMTU() (int, error) {
|
||||||
if !c.genericOpt.ok() {
|
if !c.genericOpt.ok() {
|
||||||
return 0, syscall.EINVAL
|
return 0, syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.genericOpt.sysfd()
|
s, err := netreflect.SocketOf(c.genericOpt.Conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
_, mtu, err := getMTUInfo(fd, &sockOpts[ssoPathMTU])
|
_, mtu, err := getMTUInfo(s, &sockOpts[ssoPathMTU])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -70,11 +72,11 @@ func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error {
|
||||||
if !c.payloadHandler.ok() {
|
if !c.payloadHandler.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.payloadHandler.sysfd()
|
s, err := netreflect.PacketSocketOf(c.dgramOpt.PacketConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setControlMessage(fd, &c.payloadHandler.rawOpt, cf, on)
|
return setControlMessage(s, &c.payloadHandler.rawOpt, cf, on)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeadline sets the read and write deadlines associated with the
|
// SetDeadline sets the read and write deadlines associated with the
|
||||||
|
|
|
@ -52,13 +52,13 @@ func genzsys() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// The ipv6 pacakge still supports go1.2, and so we need to
|
// The ipv6 package still supports go1.2, and so we need to
|
||||||
// take care of additional platforms in go1.3 and above for
|
// take care of additional platforms in go1.3 and above for
|
||||||
// working with go1.2.
|
// working with go1.2.
|
||||||
switch {
|
switch {
|
||||||
case runtime.GOOS == "dragonfly" || runtime.GOOS == "solaris":
|
case runtime.GOOS == "dragonfly" || runtime.GOOS == "solaris":
|
||||||
b = bytes.Replace(b, []byte("package ipv6\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv6\n"), 1)
|
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 == "mips64" || runtime.GOARCH == "mips64le" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le"):
|
case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" || runtime.GOARCH == "ppc" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"):
|
||||||
b = bytes.Replace(b, []byte("package ipv6\n"), []byte("// +build "+runtime.GOOS+","+runtime.GOARCH+"\n\npackage ipv6\n"), 1)
|
b = bytes.Replace(b, []byte("package ipv6\n"), []byte("// +build "+runtime.GOOS+","+runtime.GOARCH+"\n\npackage ipv6\n"), 1)
|
||||||
}
|
}
|
||||||
b, err = format.Source(b)
|
b, err = format.Source(b)
|
||||||
|
|
|
@ -6,7 +6,11 @@
|
||||||
|
|
||||||
package ipv6
|
package ipv6
|
||||||
|
|
||||||
import "syscall"
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/netreflect"
|
||||||
|
)
|
||||||
|
|
||||||
// TrafficClass returns the traffic class field value for outgoing
|
// TrafficClass returns the traffic class field value for outgoing
|
||||||
// packets.
|
// packets.
|
||||||
|
@ -14,11 +18,11 @@ func (c *genericOpt) TrafficClass() (int, error) {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return 0, syscall.EINVAL
|
return 0, syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.SocketOf(c.Conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return getInt(fd, &sockOpts[ssoTrafficClass])
|
return getInt(s, &sockOpts[ssoTrafficClass])
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTrafficClass sets the traffic class field value for future
|
// SetTrafficClass sets the traffic class field value for future
|
||||||
|
@ -27,11 +31,11 @@ func (c *genericOpt) SetTrafficClass(tclass int) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.SocketOf(c.Conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setInt(fd, &sockOpts[ssoTrafficClass], tclass)
|
return setInt(s, &sockOpts[ssoTrafficClass], tclass)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HopLimit returns the hop limit field value for outgoing packets.
|
// HopLimit returns the hop limit field value for outgoing packets.
|
||||||
|
@ -39,11 +43,11 @@ func (c *genericOpt) HopLimit() (int, error) {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return 0, syscall.EINVAL
|
return 0, syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.SocketOf(c.Conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return getInt(fd, &sockOpts[ssoHopLimit])
|
return getInt(s, &sockOpts[ssoHopLimit])
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHopLimit sets the hop limit field value for future outgoing
|
// SetHopLimit sets the hop limit field value for future outgoing
|
||||||
|
@ -52,9 +56,9 @@ func (c *genericOpt) SetHopLimit(hoplim int) error {
|
||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return syscall.EINVAL
|
return syscall.EINVAL
|
||||||
}
|
}
|
||||||
fd, err := c.sysfd()
|
s, err := netreflect.SocketOf(c.Conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setInt(fd, &sockOpts[ssoHopLimit], hoplim)
|
return setInt(s, &sockOpts[ssoHopLimit], hoplim)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build nacl plan9 solaris
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
func (c *genericOpt) sysfd() (int, error) {
|
|
||||||
return 0, errOpNoSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dgramOpt) sysfd() (int, error) {
|
|
||||||
return 0, errOpNoSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *payloadHandler) sysfd() (int, error) {
|
|
||||||
return 0, errOpNoSupport
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *genericOpt) sysfd() (int, error) {
|
|
||||||
switch p := c.Conn.(type) {
|
|
||||||
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
|
||||||
return sysfd(p)
|
|
||||||
}
|
|
||||||
return 0, errInvalidConnType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dgramOpt) sysfd() (int, error) {
|
|
||||||
switch p := c.PacketConn.(type) {
|
|
||||||
case *net.UDPConn, *net.IPConn:
|
|
||||||
return sysfd(p.(net.Conn))
|
|
||||||
}
|
|
||||||
return 0, errInvalidConnType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *payloadHandler) sysfd() (int, error) {
|
|
||||||
return sysfd(c.PacketConn.(net.Conn))
|
|
||||||
}
|
|
||||||
|
|
||||||
func sysfd(c net.Conn) (int, error) {
|
|
||||||
cv := reflect.ValueOf(c)
|
|
||||||
switch ce := cv.Elem(); ce.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
nfd := ce.FieldByName("conn").FieldByName("fd")
|
|
||||||
switch fe := nfd.Elem(); fe.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
fd := fe.FieldByName("sysfd")
|
|
||||||
return int(fd.Int()), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, errInvalidConnType
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"reflect"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *genericOpt) sysfd() (syscall.Handle, error) {
|
|
||||||
switch p := c.Conn.(type) {
|
|
||||||
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
|
||||||
return sysfd(p)
|
|
||||||
}
|
|
||||||
return syscall.InvalidHandle, errInvalidConnType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dgramOpt) sysfd() (syscall.Handle, error) {
|
|
||||||
switch p := c.PacketConn.(type) {
|
|
||||||
case *net.UDPConn, *net.IPConn:
|
|
||||||
return sysfd(p.(net.Conn))
|
|
||||||
}
|
|
||||||
return syscall.InvalidHandle, errInvalidConnType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *payloadHandler) sysfd() (syscall.Handle, error) {
|
|
||||||
return sysfd(c.PacketConn.(net.Conn))
|
|
||||||
}
|
|
||||||
|
|
||||||
func sysfd(c net.Conn) (syscall.Handle, error) {
|
|
||||||
cv := reflect.ValueOf(c)
|
|
||||||
switch ce := cv.Elem(); ce.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
netfd := ce.FieldByName("conn").FieldByName("fd")
|
|
||||||
switch fe := netfd.Elem(); fe.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
fd := fe.FieldByName("sysfd")
|
|
||||||
return syscall.Handle(fd.Uint()), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return syscall.InvalidHandle, errInvalidConnType
|
|
||||||
}
|
|
|
@ -4,10 +4,6 @@
|
||||||
|
|
||||||
package ipv6
|
package ipv6
|
||||||
|
|
||||||
type sysICMPv6Filter struct {
|
|
||||||
// TODO(mikio): implement this
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *sysICMPv6Filter) accept(typ ICMPType) {
|
func (f *sysICMPv6Filter) accept(typ ICMPType) {
|
||||||
// TODO(mikio): implement this
|
// TODO(mikio): implement this
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright 2016 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 (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
flag.Parse()
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
vers, _ := exec.Command("sw_vers", "-productVersion").Output()
|
||||||
|
if string(vers) == "10.8" || strings.HasPrefix(string(vers), "10.8.") {
|
||||||
|
fmt.Fprintf(os.Stderr, "# skipping tests on OS X 10.8 to avoid kernel panics; golang.org/issue/17015\n")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Exit(m.Run())
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
// +build darwin dragonfly freebsd linux netbsd openbsd windows
|
||||||
|
|
||||||
package ipv6
|
package ipv6
|
||||||
|
|
||||||
|
@ -12,11 +12,11 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setsockoptIPMreq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
func setsockoptIPMreq(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
var mreq sysIPv6Mreq
|
var mreq sysIPv6Mreq
|
||||||
copy(mreq.Multiaddr[:], grp)
|
copy(mreq.Multiaddr[:], grp)
|
||||||
if ifi != nil {
|
if ifi != nil {
|
||||||
mreq.setIfindex(ifi.Index)
|
mreq.setIfindex(ifi.Index)
|
||||||
}
|
}
|
||||||
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&mreq), sysSizeofIPv6Mreq))
|
return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, unsafe.Pointer(&mreq), sysSizeofIPv6Mreq))
|
||||||
}
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func 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))
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
// +build darwin dragonfly freebsd linux netbsd openbsd windows
|
||||||
|
|
||||||
package ipv6
|
package ipv6
|
||||||
|
|
||||||
|
@ -12,33 +12,33 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getInt(fd int, opt *sockOpt) (int, error) {
|
func getInt(s uintptr, opt *sockOpt) (int, error) {
|
||||||
if opt.name < 1 || opt.typ != ssoTypeInt {
|
if opt.name < 1 || opt.typ != ssoTypeInt {
|
||||||
return 0, errOpNoSupport
|
return 0, errOpNoSupport
|
||||||
}
|
}
|
||||||
var i int32
|
var i int32
|
||||||
l := sysSockoptLen(4)
|
l := uint32(4)
|
||||||
if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
|
if err := getsockopt(s, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
|
||||||
return 0, os.NewSyscallError("getsockopt", err)
|
return 0, os.NewSyscallError("getsockopt", err)
|
||||||
}
|
}
|
||||||
return int(i), nil
|
return int(i), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setInt(fd int, opt *sockOpt, v int) error {
|
func setInt(s uintptr, opt *sockOpt, v int) error {
|
||||||
if opt.name < 1 || opt.typ != ssoTypeInt {
|
if opt.name < 1 || opt.typ != ssoTypeInt {
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
i := int32(v)
|
i := int32(v)
|
||||||
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), sysSockoptLen(4)))
|
return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, unsafe.Pointer(&i), 4))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInterface(fd int, opt *sockOpt) (*net.Interface, error) {
|
func getInterface(s uintptr, opt *sockOpt) (*net.Interface, error) {
|
||||||
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
||||||
return nil, errOpNoSupport
|
return nil, errOpNoSupport
|
||||||
}
|
}
|
||||||
var i int32
|
var i int32
|
||||||
l := sysSockoptLen(4)
|
l := uint32(4)
|
||||||
if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
|
if err := getsockopt(s, opt.level, opt.name, unsafe.Pointer(&i), &l); err != nil {
|
||||||
return nil, os.NewSyscallError("getsockopt", err)
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
}
|
}
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
@ -51,7 +51,7 @@ func getInterface(fd int, opt *sockOpt) (*net.Interface, error) {
|
||||||
return ifi, nil
|
return ifi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setInterface(fd int, opt *sockOpt, ifi *net.Interface) error {
|
func setInterface(s uintptr, opt *sockOpt, ifi *net.Interface) error {
|
||||||
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
|
@ -59,35 +59,35 @@ func setInterface(fd int, opt *sockOpt, ifi *net.Interface) error {
|
||||||
if ifi != nil {
|
if ifi != nil {
|
||||||
i = int32(ifi.Index)
|
i = int32(ifi.Index)
|
||||||
}
|
}
|
||||||
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&i), sysSockoptLen(4)))
|
return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, unsafe.Pointer(&i), 4))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getICMPFilter(fd int, opt *sockOpt) (*ICMPFilter, error) {
|
func getICMPFilter(s uintptr, opt *sockOpt) (*ICMPFilter, error) {
|
||||||
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
|
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
|
||||||
return nil, errOpNoSupport
|
return nil, errOpNoSupport
|
||||||
}
|
}
|
||||||
var f ICMPFilter
|
var f ICMPFilter
|
||||||
l := sysSockoptLen(sysSizeofICMPv6Filter)
|
l := uint32(sysSizeofICMPv6Filter)
|
||||||
if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), &l); err != nil {
|
if err := getsockopt(s, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), &l); err != nil {
|
||||||
return nil, os.NewSyscallError("getsockopt", err)
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
}
|
}
|
||||||
return &f, nil
|
return &f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setICMPFilter(fd int, opt *sockOpt, f *ICMPFilter) error {
|
func setICMPFilter(s uintptr, opt *sockOpt, f *ICMPFilter) error {
|
||||||
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
|
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), sysSizeofICMPv6Filter))
|
return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, unsafe.Pointer(&f.sysICMPv6Filter), sysSizeofICMPv6Filter))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMTUInfo(fd int, opt *sockOpt) (*net.Interface, int, error) {
|
func getMTUInfo(s uintptr, opt *sockOpt) (*net.Interface, int, error) {
|
||||||
if opt.name < 1 || opt.typ != ssoTypeMTUInfo {
|
if opt.name < 1 || opt.typ != ssoTypeMTUInfo {
|
||||||
return nil, 0, errOpNoSupport
|
return nil, 0, errOpNoSupport
|
||||||
}
|
}
|
||||||
var mi sysIPv6Mtuinfo
|
var mi sysIPv6Mtuinfo
|
||||||
l := sysSockoptLen(sysSizeofIPv6Mtuinfo)
|
l := uint32(sysSizeofIPv6Mtuinfo)
|
||||||
if err := getsockopt(fd, opt.level, opt.name, unsafe.Pointer(&mi), &l); err != nil {
|
if err := getsockopt(s, opt.level, opt.name, unsafe.Pointer(&mi), &l); err != nil {
|
||||||
return nil, 0, os.NewSyscallError("getsockopt", err)
|
return nil, 0, os.NewSyscallError("getsockopt", err)
|
||||||
}
|
}
|
||||||
if mi.Addr.Scope_id == 0 {
|
if mi.Addr.Scope_id == 0 {
|
||||||
|
@ -100,23 +100,23 @@ func getMTUInfo(fd int, opt *sockOpt) (*net.Interface, int, error) {
|
||||||
return ifi, int(mi.Mtu), nil
|
return ifi, int(mi.Mtu), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setGroup(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
func setGroup(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
if opt.name < 1 {
|
if opt.name < 1 {
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
switch opt.typ {
|
switch opt.typ {
|
||||||
case ssoTypeIPMreq:
|
case ssoTypeIPMreq:
|
||||||
return setsockoptIPMreq(fd, opt, ifi, grp)
|
return setsockoptIPMreq(s, opt, ifi, grp)
|
||||||
case ssoTypeGroupReq:
|
case ssoTypeGroupReq:
|
||||||
return setsockoptGroupReq(fd, opt, ifi, grp)
|
return setsockoptGroupReq(s, opt, ifi, grp)
|
||||||
default:
|
default:
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setSourceGroup(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
func setSourceGroup(s uintptr, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||||
if opt.name < 1 || opt.typ != ssoTypeGroupSourceReq {
|
if opt.name < 1 || opt.typ != ssoTypeGroupSourceReq {
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
return setsockoptGroupSourceReq(fd, opt, ifi, grp, src)
|
return setsockoptGroupSourceReq(s, opt, ifi, grp, src)
|
||||||
}
|
}
|
|
@ -8,10 +8,10 @@ package ipv6
|
||||||
|
|
||||||
import "net"
|
import "net"
|
||||||
|
|
||||||
func setsockoptGroupReq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
func setsockoptGroupReq(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
func setsockoptGroupSourceReq(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
func setsockoptGroupSourceReq(s uintptr, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||||
return errOpNoSupport
|
return errOpNoSupport
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@ import (
|
||||||
|
|
||||||
var freebsd32o64 bool
|
var freebsd32o64 bool
|
||||||
|
|
||||||
func setsockoptGroupReq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
func setsockoptGroupReq(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
var gr sysGroupReq
|
var gr sysGroupReq
|
||||||
if ifi != nil {
|
if ifi != nil {
|
||||||
gr.Interface = uint32(ifi.Index)
|
gr.Interface = uint32(ifi.Index)
|
||||||
}
|
}
|
||||||
gr.setGroup(grp)
|
gr.setGroup(grp)
|
||||||
var p unsafe.Pointer
|
var p unsafe.Pointer
|
||||||
var l sysSockoptLen
|
var l uint32
|
||||||
if freebsd32o64 {
|
if freebsd32o64 {
|
||||||
var d [sysSizeofGroupReq + 4]byte
|
var d [sysSizeofGroupReq + 4]byte
|
||||||
s := (*[sysSizeofGroupReq]byte)(unsafe.Pointer(&gr))
|
s := (*[sysSizeofGroupReq]byte)(unsafe.Pointer(&gr))
|
||||||
|
@ -33,17 +33,17 @@ func setsockoptGroupReq(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) er
|
||||||
p = unsafe.Pointer(&gr)
|
p = unsafe.Pointer(&gr)
|
||||||
l = sysSizeofGroupReq
|
l = sysSizeofGroupReq
|
||||||
}
|
}
|
||||||
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, p, l))
|
return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, p, l))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setsockoptGroupSourceReq(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
func setsockoptGroupSourceReq(s uintptr, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||||
var gsr sysGroupSourceReq
|
var gsr sysGroupSourceReq
|
||||||
if ifi != nil {
|
if ifi != nil {
|
||||||
gsr.Interface = uint32(ifi.Index)
|
gsr.Interface = uint32(ifi.Index)
|
||||||
}
|
}
|
||||||
gsr.setSourceGroup(grp, src)
|
gsr.setSourceGroup(grp, src)
|
||||||
var p unsafe.Pointer
|
var p unsafe.Pointer
|
||||||
var l sysSockoptLen
|
var l uint32
|
||||||
if freebsd32o64 {
|
if freebsd32o64 {
|
||||||
var d [sysSizeofGroupSourceReq + 4]byte
|
var d [sysSizeofGroupSourceReq + 4]byte
|
||||||
s := (*[sysSizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))
|
s := (*[sysSizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))
|
||||||
|
@ -55,5 +55,5 @@ func setsockoptGroupSourceReq(fd int, opt *sockOpt, ifi *net.Interface, grp, src
|
||||||
p = unsafe.Pointer(&gsr)
|
p = unsafe.Pointer(&gsr)
|
||||||
l = sysSizeofGroupSourceReq
|
l = sysSizeofGroupSourceReq
|
||||||
}
|
}
|
||||||
return os.NewSyscallError("setsockopt", setsockopt(fd, opt.level, opt.name, p, l))
|
return os.NewSyscallError("setsockopt", setsockopt(s, opt.level, opt.name, p, l))
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,6 @@ package ipv6
|
||||||
|
|
||||||
import "net"
|
import "net"
|
||||||
|
|
||||||
func getMTUInfo(fd int, opt *sockOpt) (*net.Interface, int, error) {
|
func getMTUInfo(s uintptr, opt *sockOpt) (*net.Interface, int, error) {
|
||||||
return nil, 0, errOpNoSupport
|
return nil, 0, errOpNoSupport
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func 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
|
|
||||||
}
|
|
|
@ -13,8 +13,6 @@ import (
|
||||||
"golang.org/x/net/internal/iana"
|
"golang.org/x/net/internal/iana"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sysSockoptLen int32
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctlOpts = [ctlMax]ctlOpt{
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
||||||
|
|
|
@ -12,8 +12,6 @@ import (
|
||||||
"golang.org/x/net/internal/iana"
|
"golang.org/x/net/internal/iana"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sysSockoptLen int32
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctlOpts = [ctlMax]ctlOpt{
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
ctlHopLimit: {sysIPV6_2292HOPLIMIT, 4, marshal2292HopLimit, parseHopLimit},
|
ctlHopLimit: {sysIPV6_2292HOPLIMIT, 4, marshal2292HopLimit, parseHopLimit},
|
||||||
|
|
|
@ -14,8 +14,6 @@ import (
|
||||||
"golang.org/x/net/internal/iana"
|
"golang.org/x/net/internal/iana"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sysSockoptLen int32
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctlOpts = [ctlMax]ctlOpt{
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
||||||
|
|
|
@ -12,8 +12,6 @@ import (
|
||||||
"golang.org/x/net/internal/iana"
|
"golang.org/x/net/internal/iana"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sysSockoptLen int32
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctlOpts = [ctlMax]ctlOpt{
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
package ipv6
|
package ipv6
|
||||||
|
|
||||||
type sysSockoptLen int32
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctlOpts = [ctlMax]ctlOpt{}
|
ctlOpts = [ctlMax]ctlOpt{}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ const (
|
||||||
|
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
|
|
||||||
sysSizeofIPv6Mreq = 0x14
|
sysSizeofIPv6Mreq = 0x14
|
||||||
|
sysSizeofIPv6Mtuinfo = 0x20
|
||||||
|
sysSizeofICMPv6Filter = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
type sysSockaddrInet6 struct {
|
type sysSockaddrInet6 struct {
|
||||||
|
@ -39,6 +41,15 @@ type sysIPv6Mreq struct {
|
||||||
Interface uint32
|
Interface uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysIPv6Mtuinfo struct {
|
||||||
|
Addr sysSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysICMPv6Filter struct {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctlOpts = [ctlMax]ctlOpt{}
|
ctlOpts = [ctlMax]ctlOpt{}
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,15 @@ const (
|
||||||
|
|
||||||
func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
|
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 {
|
func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
|
||||||
if _, errno := socketcall(sysGETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
if _, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
||||||
return error(errno)
|
return error(errno)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setsockopt(fd, level, name int, v unsafe.Pointer, l sysSockoptLen) error {
|
func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
|
||||||
if _, errno := socketcall(sysSETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
if _, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
||||||
return error(errno)
|
return error(errno)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -11,15 +11,15 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getsockopt(fd, level, name int, v unsafe.Pointer, l *sysSockoptLen) error {
|
func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
|
||||||
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
||||||
return error(errno)
|
return error(errno)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setsockopt(fd, level, name int, v unsafe.Pointer, l sysSockoptLen) error {
|
func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
|
||||||
if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
||||||
return error(errno)
|
return error(errno)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2016 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
|
||||||
|
return syscall.Getsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(v), (*int32)(unsafe.Pointer(l)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
|
||||||
|
return syscall.Setsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(v), int32(l))
|
||||||
|
}
|
|
@ -84,6 +84,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
sysICMPV6_FILTER_PASSONLY = 0x4
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = 0x80
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
sysSizeofInet6Pktinfo = 0x14
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
@ -150,3 +153,16 @@ type sysGroupSourceReq struct {
|
||||||
type sysICMPv6Filter struct {
|
type sysICMPv6Filter struct {
|
||||||
Data [8]uint32
|
Data [8]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [2]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
|
@ -84,6 +84,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
sysICMPV6_FILTER_PASSONLY = 0x4
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = 0x80
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
sysSizeofInet6Pktinfo = 0x14
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
@ -152,3 +155,16 @@ type sysGroupSourceReq struct {
|
||||||
type sysICMPv6Filter struct {
|
type sysICMPv6Filter struct {
|
||||||
Data [8]uint32
|
Data [8]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [6]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
|
@ -84,6 +84,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
sysICMPV6_FILTER_PASSONLY = 0x4
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = 0x80
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
sysSizeofInet6Pktinfo = 0x14
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
@ -150,3 +153,16 @@ type sysGroupSourceReq struct {
|
||||||
type sysICMPv6Filter struct {
|
type sysICMPv6Filter struct {
|
||||||
Data [8]uint32
|
Data [8]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [2]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
|
@ -86,6 +86,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
sysICMPV6_FILTER_PASSONLY = 0x4
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = 0x80
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
sysSizeofInet6Pktinfo = 0x14
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
@ -154,3 +157,16 @@ type sysGroupSourceReq struct {
|
||||||
type sysICMPv6Filter struct {
|
type sysICMPv6Filter struct {
|
||||||
Data [8]uint32
|
Data [8]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [6]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
|
@ -86,6 +86,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
sysICMPV6_FILTER_PASSONLY = 0x4
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = 0x80
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
sysSizeofInet6Pktinfo = 0x14
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
@ -154,3 +157,16 @@ type sysGroupSourceReq struct {
|
||||||
type sysICMPv6Filter struct {
|
type sysICMPv6Filter struct {
|
||||||
Data [8]uint32
|
Data [8]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [6]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
|
@ -86,6 +86,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
sysICMPV6_FILTER_PASSONLY = 0x4
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = 0x80
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
sysSizeofInet6Pktinfo = 0x14
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
@ -154,3 +157,16 @@ type sysGroupSourceReq struct {
|
||||||
type sysICMPv6Filter struct {
|
type sysICMPv6Filter struct {
|
||||||
Data [8]uint32
|
Data [8]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [6]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_linux.go
|
||||||
|
|
||||||
|
// +build linux,ppc
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
|
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]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [2]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
|
@ -86,6 +86,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
sysICMPV6_FILTER_PASSONLY = 0x4
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = 0x80
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
sysSizeofInet6Pktinfo = 0x14
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
@ -154,3 +157,16 @@ type sysGroupSourceReq struct {
|
||||||
type sysICMPv6Filter struct {
|
type sysICMPv6Filter struct {
|
||||||
Data [8]uint32
|
Data [8]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [6]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
|
@ -86,6 +86,9 @@ const (
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
sysICMPV6_FILTER_BLOCKOTHERS = 0x3
|
||||||
sysICMPV6_FILTER_PASSONLY = 0x4
|
sysICMPV6_FILTER_PASSONLY = 0x4
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
sysSizeofKernelSockaddrStorage = 0x80
|
sysSizeofKernelSockaddrStorage = 0x80
|
||||||
sysSizeofSockaddrInet6 = 0x1c
|
sysSizeofSockaddrInet6 = 0x1c
|
||||||
sysSizeofInet6Pktinfo = 0x14
|
sysSizeofInet6Pktinfo = 0x14
|
||||||
|
@ -154,3 +157,16 @@ type sysGroupSourceReq struct {
|
||||||
type sysICMPv6Filter struct {
|
type sysICMPv6Filter struct {
|
||||||
Data [8]uint32
|
Data [8]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [6]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_linux.go
|
||||||
|
|
||||||
|
// +build linux,s390x
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
sysSOL_SOCKET = 0x1
|
||||||
|
sysSO_ATTACH_FILTER = 0x1a
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFProg struct {
|
||||||
|
Len uint16
|
||||||
|
Pad_cgo_0 [6]byte
|
||||||
|
Filter *sysSockFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockFilter struct {
|
||||||
|
Code uint16
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
K uint32
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -234,7 +234,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) (
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
as[i] = a
|
as[i] = a
|
||||||
b = b[roundup(int(b[0])):]
|
l := roundup(int(b[0]))
|
||||||
|
if len(b) < l {
|
||||||
|
return nil, errMessageTooShort
|
||||||
|
}
|
||||||
|
b = b[l:]
|
||||||
case sysAF_INET, sysAF_INET6:
|
case sysAF_INET, sysAF_INET6:
|
||||||
af = int(b[1])
|
af = int(b[1])
|
||||||
a, err := parseInetAddr(af, b)
|
a, err := parseInetAddr(af, b)
|
||||||
|
@ -242,7 +246,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) (
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
as[i] = a
|
as[i] = a
|
||||||
b = b[roundup(int(b[0])):]
|
l := roundup(int(b[0]))
|
||||||
|
if len(b) < l {
|
||||||
|
return nil, errMessageTooShort
|
||||||
|
}
|
||||||
|
b = b[l:]
|
||||||
default:
|
default:
|
||||||
l, a, err := fn(af, b)
|
l, a, err := fn(af, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -262,7 +270,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) (
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
as[i] = a
|
as[i] = a
|
||||||
b = b[roundup(int(b[0])):]
|
l := roundup(int(b[0]))
|
||||||
|
if len(b) < l {
|
||||||
|
return nil, errMessageTooShort
|
||||||
|
}
|
||||||
|
b = b[l:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return as[:], nil
|
return as[:], nil
|
||||||
|
|
|
@ -13,12 +13,12 @@ func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, erro
|
||||||
extOff = int(nativeEndian.Uint16(b[18:20]))
|
extOff = int(nativeEndian.Uint16(b[18:20]))
|
||||||
bodyOff = int(nativeEndian.Uint16(b[16:18]))
|
bodyOff = int(nativeEndian.Uint16(b[16:18]))
|
||||||
} else {
|
} else {
|
||||||
if len(b) < w.bodyOff {
|
|
||||||
return nil, errMessageTooShort
|
|
||||||
}
|
|
||||||
extOff = w.extOff
|
extOff = w.extOff
|
||||||
bodyOff = w.bodyOff
|
bodyOff = w.bodyOff
|
||||||
}
|
}
|
||||||
|
if len(b) < extOff || len(b) < bodyOff {
|
||||||
|
return nil, errInvalidMessage
|
||||||
|
}
|
||||||
l := int(nativeEndian.Uint16(b[:2]))
|
l := int(nativeEndian.Uint16(b[:2]))
|
||||||
if len(b) < l {
|
if len(b) < l {
|
||||||
return nil, errInvalidMessage
|
return nil, errInvalidMessage
|
||||||
|
@ -53,11 +53,11 @@ func (w *wireFormat) parseInterfaceAddrMessage(typ RIBType, b []byte) (Message,
|
||||||
}
|
}
|
||||||
bodyOff = int(nativeEndian.Uint16(b[16:18]))
|
bodyOff = int(nativeEndian.Uint16(b[16:18]))
|
||||||
} else {
|
} else {
|
||||||
if len(b) < w.bodyOff {
|
|
||||||
return nil, errMessageTooShort
|
|
||||||
}
|
|
||||||
bodyOff = w.bodyOff
|
bodyOff = w.bodyOff
|
||||||
}
|
}
|
||||||
|
if len(b) < bodyOff {
|
||||||
|
return nil, errInvalidMessage
|
||||||
|
}
|
||||||
l := int(nativeEndian.Uint16(b[:2]))
|
l := int(nativeEndian.Uint16(b[:2]))
|
||||||
if len(b) < l {
|
if len(b) < l {
|
||||||
return nil, errInvalidMessage
|
return nil, errInvalidMessage
|
||||||
|
|
|
@ -24,7 +24,11 @@ func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) {
|
||||||
Addrs: make([]Addr, sysRTAX_MAX),
|
Addrs: make([]Addr, sysRTAX_MAX),
|
||||||
raw: b[:l],
|
raw: b[:l],
|
||||||
}
|
}
|
||||||
a, err := parseLinkAddr(b[int(nativeEndian.Uint16(b[4:6])):])
|
ll := int(nativeEndian.Uint16(b[4:6]))
|
||||||
|
if len(b) < ll {
|
||||||
|
return nil, errInvalidMessage
|
||||||
|
}
|
||||||
|
a, err := parseLinkAddr(b[ll:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -42,6 +46,9 @@ func (*wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, erro
|
||||||
return nil, errInvalidMessage
|
return nil, errInvalidMessage
|
||||||
}
|
}
|
||||||
bodyOff := int(nativeEndian.Uint16(b[4:6]))
|
bodyOff := int(nativeEndian.Uint16(b[4:6]))
|
||||||
|
if len(b) < bodyOff {
|
||||||
|
return nil, errInvalidMessage
|
||||||
|
}
|
||||||
m := &InterfaceAddrMessage{
|
m := &InterfaceAddrMessage{
|
||||||
Version: int(b[2]),
|
Version: int(b[2]),
|
||||||
Type: int(b[3]),
|
Type: int(b[3]),
|
||||||
|
|
|
@ -42,6 +42,12 @@ func ParseRIB(typ RIBType, b []byte) ([]Message, error) {
|
||||||
for len(b) > 4 {
|
for len(b) > 4 {
|
||||||
nmsgs++
|
nmsgs++
|
||||||
l := int(nativeEndian.Uint16(b[:2]))
|
l := int(nativeEndian.Uint16(b[:2]))
|
||||||
|
if l == 0 {
|
||||||
|
return nil, errInvalidMessage
|
||||||
|
}
|
||||||
|
if len(b) < l {
|
||||||
|
return nil, errMessageTooShort
|
||||||
|
}
|
||||||
if b[2] != sysRTM_VERSION {
|
if b[2] != sysRTM_VERSION {
|
||||||
b = b[l:]
|
b = b[l:]
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -19,7 +19,11 @@ func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) {
|
||||||
Index: int(nativeEndian.Uint16(b[6:8])),
|
Index: int(nativeEndian.Uint16(b[6:8])),
|
||||||
raw: b[:l],
|
raw: b[:l],
|
||||||
}
|
}
|
||||||
as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[int(nativeEndian.Uint16(b[4:6])):])
|
ll := int(nativeEndian.Uint16(b[4:6]))
|
||||||
|
if len(b) < ll {
|
||||||
|
return nil, errInvalidMessage
|
||||||
|
}
|
||||||
|
as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[ll:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/net/context",
|
"importpath": "golang.org/x/net/context",
|
||||||
"repository": "https://go.googlesource.com/net",
|
"repository": "https://go.googlesource.com/net",
|
||||||
"revision": "c4c3ea71919de159c9e246d7be66deb7f0a39a58",
|
"revision": "749a502dd1eaf3e5bfd4f8956748c502357c0bbe",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/context",
|
"path": "/context",
|
||||||
"notests": true
|
"notests": true
|
||||||
|
@ -300,24 +300,32 @@
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/internal/iana"
|
"path": "/internal/iana"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"importpath": "golang.org/x/net/internal/netreflect",
|
||||||
|
"repository": "https://go.googlesource.com/net",
|
||||||
|
"revision": "749a502dd1eaf3e5bfd4f8956748c502357c0bbe",
|
||||||
|
"branch": "master",
|
||||||
|
"path": "/internal/netreflect",
|
||||||
|
"notests": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/net/ipv6",
|
"importpath": "golang.org/x/net/ipv6",
|
||||||
"repository": "https://go.googlesource.com/net",
|
"repository": "https://go.googlesource.com/net",
|
||||||
"revision": "08f168e593b5aab61849054b77981de812666697",
|
"revision": "749a502dd1eaf3e5bfd4f8956748c502357c0bbe",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/ipv6"
|
"path": "/ipv6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/net/proxy",
|
"importpath": "golang.org/x/net/proxy",
|
||||||
"repository": "https://go.googlesource.com/net",
|
"repository": "https://go.googlesource.com/net",
|
||||||
"revision": "08f168e593b5aab61849054b77981de812666697",
|
"revision": "749a502dd1eaf3e5bfd4f8956748c502357c0bbe",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/proxy"
|
"path": "/proxy"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/net/route",
|
"importpath": "golang.org/x/net/route",
|
||||||
"repository": "https://go.googlesource.com/net",
|
"repository": "https://go.googlesource.com/net",
|
||||||
"revision": "b400c2eff1badec7022a8c8f5bea058b6315eed7",
|
"revision": "749a502dd1eaf3e5bfd4f8956748c502357c0bbe",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/route",
|
"path": "/route",
|
||||||
"notests": true
|
"notests": true
|
||||||
|
|
Loading…
Reference in New Issue