From c3cde444806f8a89c7029ffd3b024f98748a85a4 Mon Sep 17 00:00:00 2001 From: Aithal Date: Fri, 17 Feb 2017 17:04:53 -0800 Subject: [PATCH 1/4] pkg/ns: refactored so that builds succeed on non-linux platforms moved functions that depend on linux packages (sys/unix) into a separate file and added nop methods with a build tag for non-linux platforms in a new file. --- pkg/ns/ns.go | 124 +-------------------------------- pkg/ns/ns_linux.go | 144 +++++++++++++++++++++++++++++++++++++++ pkg/ns/ns_unspecified.go | 33 +++++++++ 3 files changed, 180 insertions(+), 121 deletions(-) create mode 100644 pkg/ns/ns_linux.go create mode 100644 pkg/ns/ns_unspecified.go diff --git a/pkg/ns/ns.go b/pkg/ns/ns.go index 220dd694..428fb77f 100644 --- a/pkg/ns/ns.go +++ b/pkg/ns/ns.go @@ -15,15 +15,12 @@ package ns import ( - "crypto/rand" + "errors" "fmt" "os" - "path" "runtime" "sync" "syscall" - - "golang.org/x/sys/unix" ) type NetNS interface { @@ -65,12 +62,8 @@ type netNS struct { // netNS implements the NetNS interface var _ NetNS = &netNS{} -func getCurrentThreadNetNSPath() string { - // /proc/self/ns/net returns the namespace of the main thread, not - // of whatever thread this goroutine is running on. Make sure we - // use the thread's net namespace since the thread is switching around - return fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid()) -} +// NotImplementedError is used to indicate that a method is not implemented for the given platform +var NotImplementedError = errors.New("Not Implemented") // Returns an object representing the current OS thread's network namespace func GetCurrentNS() (NetNS, error) { @@ -125,82 +118,6 @@ func GetNS(nspath string) (NetNS, error) { return &netNS{file: fd}, nil } -// Creates a new persistent network namespace and returns an object -// representing that namespace, without switching to it -func NewNS() (NetNS, error) { - const nsRunDir = "/var/run/netns" - - b := make([]byte, 16) - _, err := rand.Reader.Read(b) - if err != nil { - return nil, fmt.Errorf("failed to generate random netns name: %v", err) - } - - err = os.MkdirAll(nsRunDir, 0755) - if err != nil { - return nil, err - } - - // create an empty file at the mount point - nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) - nsPath := path.Join(nsRunDir, nsName) - mountPointFd, err := os.Create(nsPath) - if err != nil { - return nil, err - } - mountPointFd.Close() - - // Ensure the mount point is cleaned up on errors; if the namespace - // was successfully mounted this will have no effect because the file - // is in-use - defer os.RemoveAll(nsPath) - - var wg sync.WaitGroup - wg.Add(1) - - // do namespace work in a dedicated goroutine, so that we can safely - // Lock/Unlock OSThread without upsetting the lock/unlock state of - // the caller of this function - var fd *os.File - go (func() { - defer wg.Done() - runtime.LockOSThread() - - var origNS NetNS - origNS, err = GetNS(getCurrentThreadNetNSPath()) - if err != nil { - return - } - defer origNS.Close() - - // create a new netns on the current thread - err = unix.Unshare(unix.CLONE_NEWNET) - if err != nil { - return - } - defer origNS.Set() - - // bind mount the new netns from the current thread onto the mount point - err = unix.Mount(getCurrentThreadNetNSPath(), nsPath, "none", unix.MS_BIND, "") - if err != nil { - return - } - - fd, err = os.Open(nsPath) - if err != nil { - return - } - })() - wg.Wait() - - if err != nil { - unix.Unmount(nsPath, unix.MNT_DETACH) - return nil, fmt.Errorf("failed to create namespace: %v", err) - } - - return &netNS{file: fd, mounted: true}, nil -} - func (ns *netNS) Path() string { return ns.file.Name() } @@ -216,29 +133,6 @@ func (ns *netNS) errorIfClosed() error { return nil } -func (ns *netNS) Close() error { - if err := ns.errorIfClosed(); err != nil { - return err - } - - if err := ns.file.Close(); err != nil { - return fmt.Errorf("Failed to close %q: %v", ns.file.Name(), err) - } - ns.closed = true - - if ns.mounted { - if err := unix.Unmount(ns.file.Name(), unix.MNT_DETACH); err != nil { - return fmt.Errorf("Failed to unmount namespace %s: %v", ns.file.Name(), err) - } - if err := os.RemoveAll(ns.file.Name()); err != nil { - return fmt.Errorf("Failed to clean up namespace %s: %v", ns.file.Name(), err) - } - ns.mounted = false - } - - return nil -} - func (ns *netNS) Do(toRun func(NetNS) error) error { if err := ns.errorIfClosed(); err != nil { return err @@ -281,18 +175,6 @@ func (ns *netNS) Do(toRun func(NetNS) error) error { return innerError } -func (ns *netNS) Set() error { - if err := ns.errorIfClosed(); err != nil { - return err - } - - if _, _, err := unix.Syscall(unix.SYS_SETNS, ns.Fd(), uintptr(unix.CLONE_NEWNET), 0); err != 0 { - return fmt.Errorf("Error switching to ns %v: %v", ns.file.Name(), err) - } - - return nil -} - // WithNetNSPath executes the passed closure under the given network // namespace, restoring the original namespace afterwards. func WithNetNSPath(nspath string, toRun func(NetNS) error) error { diff --git a/pkg/ns/ns_linux.go b/pkg/ns/ns_linux.go new file mode 100644 index 00000000..0746f159 --- /dev/null +++ b/pkg/ns/ns_linux.go @@ -0,0 +1,144 @@ +// Copyright 2015-2017 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ns + +import ( + "crypto/rand" + "fmt" + "os" + "path" + "runtime" + "sync" + + "golang.org/x/sys/unix" +) + +func getCurrentThreadNetNSPath() string { + // /proc/self/ns/net returns the namespace of the main thread, not + // of whatever thread this goroutine is running on. Make sure we + // use the thread's net namespace since the thread is switching around + return fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid()) +} + +// Creates a new persistent network namespace and returns an object +// representing that namespace, without switching to it +func NewNS() (NetNS, error) { + const nsRunDir = "/var/run/netns" + + b := make([]byte, 16) + _, err := rand.Reader.Read(b) + if err != nil { + return nil, fmt.Errorf("failed to generate random netns name: %v", err) + } + + err = os.MkdirAll(nsRunDir, 0755) + if err != nil { + return nil, err + } + + // create an empty file at the mount point + nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) + nsPath := path.Join(nsRunDir, nsName) + mountPointFd, err := os.Create(nsPath) + if err != nil { + return nil, err + } + mountPointFd.Close() + + // Ensure the mount point is cleaned up on errors; if the namespace + // was successfully mounted this will have no effect because the file + // is in-use + defer os.RemoveAll(nsPath) + + var wg sync.WaitGroup + wg.Add(1) + + // do namespace work in a dedicated goroutine, so that we can safely + // Lock/Unlock OSThread without upsetting the lock/unlock state of + // the caller of this function + var fd *os.File + go (func() { + defer wg.Done() + runtime.LockOSThread() + + var origNS NetNS + origNS, err = GetNS(getCurrentThreadNetNSPath()) + if err != nil { + return + } + defer origNS.Close() + + // create a new netns on the current thread + err = unix.Unshare(unix.CLONE_NEWNET) + if err != nil { + return + } + defer origNS.Set() + + // bind mount the new netns from the current thread onto the mount point + err = unix.Mount(getCurrentThreadNetNSPath(), nsPath, "none", unix.MS_BIND, "") + if err != nil { + return + } + + fd, err = os.Open(nsPath) + if err != nil { + return + } + })() + wg.Wait() + + if err != nil { + unix.Unmount(nsPath, unix.MNT_DETACH) + return nil, fmt.Errorf("failed to create namespace: %v", err) + } + + return &netNS{file: fd, mounted: true}, nil +} + +func (ns *netNS) Close() error { + if err := ns.errorIfClosed(); err != nil { + return err + } + + if err := ns.file.Close(); err != nil { + return fmt.Errorf("Failed to close %q: %v", ns.file.Name(), err) + } + ns.closed = true + + if ns.mounted { + if err := unix.Unmount(ns.file.Name(), unix.MNT_DETACH); err != nil { + return fmt.Errorf("Failed to unmount namespace %s: %v", ns.file.Name(), err) + } + if err := os.RemoveAll(ns.file.Name()); err != nil { + return fmt.Errorf("Failed to clean up namespace %s: %v", ns.file.Name(), err) + } + ns.mounted = false + } + + return nil +} + +func (ns *netNS) Set() error { + if err := ns.errorIfClosed(); err != nil { + return err + } + + if _, _, err := unix.Syscall(unix.SYS_SETNS, ns.Fd(), uintptr(unix.CLONE_NEWNET), 0); err != 0 { + return fmt.Errorf("Error switching to ns %v: %v", ns.file.Name(), err) + } + + return nil +} diff --git a/pkg/ns/ns_unspecified.go b/pkg/ns/ns_unspecified.go new file mode 100644 index 00000000..da8b1796 --- /dev/null +++ b/pkg/ns/ns_unspecified.go @@ -0,0 +1,33 @@ +// Copyright 2015-2017 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !linux + +package ns + +func getCurrentThreadNetNSPath() string { + return "" +} + +func NewNS() (NetNS, error) { + return nil, NotImplementedError +} + +func (ns *netNS) Close() error { + return NotImplementedError +} + +func (ns *netNS) Set() error { + return NotImplementedError +} From 0dc0845c51f2e6acaaf157383900c64ef7ac8809 Mon Sep 17 00:00:00 2001 From: Aithal Date: Thu, 23 Feb 2017 09:50:48 -0800 Subject: [PATCH 2/4] pkg/ns, pkg/types: refactored non linux build fix code to Make GetCurrentNS platform specific instead of getCurrentThreadNetNSPath --- pkg/ns/ns.go | 13 ++----------- pkg/ns/ns_linux.go | 5 +++++ pkg/ns/ns_unspecified.go | 13 ++++++++----- pkg/types/types.go | 4 ++++ 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/pkg/ns/ns.go b/pkg/ns/ns.go index 428fb77f..c212f489 100644 --- a/pkg/ns/ns.go +++ b/pkg/ns/ns.go @@ -15,7 +15,6 @@ package ns import ( - "errors" "fmt" "os" "runtime" @@ -62,14 +61,6 @@ type netNS struct { // netNS implements the NetNS interface var _ NetNS = &netNS{} -// NotImplementedError is used to indicate that a method is not implemented for the given platform -var NotImplementedError = errors.New("Not Implemented") - -// Returns an object representing the current OS thread's network namespace -func GetCurrentNS() (NetNS, error) { - return GetNS(getCurrentThreadNetNSPath()) -} - const ( // https://github.com/torvalds/linux/blob/master/include/uapi/linux/magic.h NSFS_MAGIC = 0x6e736673 @@ -139,7 +130,7 @@ func (ns *netNS) Do(toRun func(NetNS) error) error { } containedCall := func(hostNS NetNS) error { - threadNS, err := GetNS(getCurrentThreadNetNSPath()) + threadNS, err := GetCurrentNS() if err != nil { return fmt.Errorf("failed to open current netns: %v", err) } @@ -155,7 +146,7 @@ func (ns *netNS) Do(toRun func(NetNS) error) error { } // save a handle to current network namespace - hostNS, err := GetNS(getCurrentThreadNetNSPath()) + hostNS, err := GetCurrentNS() if err != nil { return fmt.Errorf("Failed to open current namespace: %v", err) } diff --git a/pkg/ns/ns_linux.go b/pkg/ns/ns_linux.go index 0746f159..c9e1b4f0 100644 --- a/pkg/ns/ns_linux.go +++ b/pkg/ns/ns_linux.go @@ -25,6 +25,11 @@ import ( "golang.org/x/sys/unix" ) +// Returns an object representing the current OS thread's network namespace +func GetCurrentNS() (NetNS, error) { + return GetNS(getCurrentThreadNetNSPath()) +} + func getCurrentThreadNetNSPath() string { // /proc/self/ns/net returns the namespace of the main thread, not // of whatever thread this goroutine is running on. Make sure we diff --git a/pkg/ns/ns_unspecified.go b/pkg/ns/ns_unspecified.go index da8b1796..41b44686 100644 --- a/pkg/ns/ns_unspecified.go +++ b/pkg/ns/ns_unspecified.go @@ -16,18 +16,21 @@ package ns -func getCurrentThreadNetNSPath() string { - return "" +import "github.com/containernetworking/cni/pkg/types" + +// Returns an object representing the current OS thread's network namespace +func GetCurrentNS() (NetNS, error) { + return nil, types.NotImplementedError } func NewNS() (NetNS, error) { - return nil, NotImplementedError + return nil, types.NotImplementedError } func (ns *netNS) Close() error { - return NotImplementedError + return types.NotImplementedError } func (ns *netNS) Set() error { - return NotImplementedError + return types.NotImplementedError } diff --git a/pkg/types/types.go b/pkg/types/types.go index a81ac702..b7c27de1 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -16,6 +16,7 @@ package types import ( "encoding/json" + "errors" "fmt" "net" "os" @@ -178,3 +179,6 @@ func prettyPrint(obj interface{}) error { _, err = os.Stdout.Write(data) return err } + +// NotImplementedError is used to indicate that a method is not implemented for the given platform +var NotImplementedError = errors.New("Not Implemented") From 7eeb21a999478af1129bf549ba8c0cbbe6266191 Mon Sep 17 00:00:00 2001 From: Aithal Date: Thu, 23 Feb 2017 09:52:13 -0800 Subject: [PATCH 3/4] pkg/ip: refactored so that builds succeed on non-linux platforms moved functions that depend on linux packages into a separate file and added nop methods with a build tag for non-linux platforms in a new file. --- pkg/ip/route.go | 20 ------------------ pkg/ip/route_linux.go | 41 +++++++++++++++++++++++++++++++++++++ pkg/ip/route_unspecified.go | 34 ++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 pkg/ip/route_linux.go create mode 100644 pkg/ip/route_unspecified.go diff --git a/pkg/ip/route.go b/pkg/ip/route.go index 6c8658b2..1325a47a 100644 --- a/pkg/ip/route.go +++ b/pkg/ip/route.go @@ -25,23 +25,3 @@ func AddDefaultRoute(gw net.IP, dev netlink.Link) error { _, defNet, _ := net.ParseCIDR("0.0.0.0/0") return AddRoute(defNet, gw, dev) } - -// AddRoute adds a universally-scoped route to a device. -func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { - return netlink.RouteAdd(&netlink.Route{ - LinkIndex: dev.Attrs().Index, - Scope: netlink.SCOPE_UNIVERSE, - Dst: ipn, - Gw: gw, - }) -} - -// AddHostRoute adds a host-scoped route to a device. -func AddHostRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { - return netlink.RouteAdd(&netlink.Route{ - LinkIndex: dev.Attrs().Index, - Scope: netlink.SCOPE_HOST, - Dst: ipn, - Gw: gw, - }) -} diff --git a/pkg/ip/route_linux.go b/pkg/ip/route_linux.go new file mode 100644 index 00000000..8b11807d --- /dev/null +++ b/pkg/ip/route_linux.go @@ -0,0 +1,41 @@ +// Copyright 2015-2017 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ip + +import ( + "net" + + "github.com/vishvananda/netlink" +) + +// AddRoute adds a universally-scoped route to a device. +func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { + return netlink.RouteAdd(&netlink.Route{ + LinkIndex: dev.Attrs().Index, + Scope: netlink.SCOPE_UNIVERSE, + Dst: ipn, + Gw: gw, + }) +} + +// AddHostRoute adds a host-scoped route to a device. +func AddHostRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { + return netlink.RouteAdd(&netlink.Route{ + LinkIndex: dev.Attrs().Index, + Scope: netlink.SCOPE_HOST, + Dst: ipn, + Gw: gw, + }) +} diff --git a/pkg/ip/route_unspecified.go b/pkg/ip/route_unspecified.go new file mode 100644 index 00000000..7e79fdef --- /dev/null +++ b/pkg/ip/route_unspecified.go @@ -0,0 +1,34 @@ +// Copyright 2015-2017 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !linux + +package ip + +import ( + "net" + + "github.com/containernetworking/cni/pkg/types" + "github.com/vishvananda/netlink" +) + +// AddRoute adds a universally-scoped route to a device. +func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { + return types.NotImplementedError +} + +// AddHostRoute adds a host-scoped route to a device. +func AddHostRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { + return types.NotImplementedError +} From 460e1c5be3a13ec7ead44dc35178fd35f4808e1a Mon Sep 17 00:00:00 2001 From: Aithal Date: Thu, 23 Feb 2017 09:53:11 -0800 Subject: [PATCH 4/4] vendor: Update vishvanana/netlink dependency --- Godeps/Godeps.json | 54 +--- .../github.com/vishvananda/netlink/Makefile | 2 +- vendor/github.com/vishvananda/netlink/addr.go | 15 +- .../vishvananda/netlink/addr_linux.go | 26 +- .../vishvananda/netlink/handle_linux.go | 25 ++ .../vishvananda/netlink/handle_unspecified.go | 218 +++++++++++++++ vendor/github.com/vishvananda/netlink/link.go | 152 ++++++++++- .../vishvananda/netlink/link_linux.go | 214 ++++++++++++--- .../github.com/vishvananda/netlink/netlink.go | 10 +- .../vishvananda/netlink/netlink_linux.go | 7 +- .../netlink/netlink_unspecified.go | 106 ++++++-- .../vishvananda/netlink/nl/link_linux.go | 34 +++ .../vishvananda/netlink/nl/mpls_linux.go | 36 +++ .../vishvananda/netlink/nl/nl_linux.go | 14 +- .../vishvananda/netlink/nl/nl_unspecified.go | 11 + .../vishvananda/netlink/nl/route_linux.go | 28 +- .../vishvananda/netlink/nl/syscall.go | 31 +++ .../vishvananda/netlink/nl/xfrm_linux.go | 72 +++-- .../netlink/nl/xfrm_monitor_linux.go | 32 +++ .../netlink/nl/xfrm_state_linux.go | 78 +++++- .../github.com/vishvananda/netlink/order.go | 32 +++ .../vishvananda/netlink/protinfo.go | 5 +- .../vishvananda/netlink/protinfo_linux.go | 40 +-- .../github.com/vishvananda/netlink/qdisc.go | 9 +- .../vishvananda/netlink/qdisc_linux.go | 18 +- .../github.com/vishvananda/netlink/route.go | 60 +++- .../vishvananda/netlink/route_linux.go | 257 ++++++++++++++++-- .../vishvananda/netlink/route_unspecified.go | 4 + .../github.com/vishvananda/netlink/socket.go | 27 ++ .../vishvananda/netlink/socket_linux.go | 159 +++++++++++ .../vishvananda/netlink/xfrm_monitor_linux.go | 98 +++++++ .../vishvananda/netlink/xfrm_state.go | 5 +- .../vishvananda/netlink/xfrm_state_linux.go | 112 ++++++-- vendor/golang.org/x/sys/AUTHORS | 3 + vendor/golang.org/x/sys/CONTRIBUTORS | 3 + vendor/golang.org/x/sys/unix/mkall.sh | 0 vendor/golang.org/x/sys/unix/mkerrors.sh | 0 vendor/golang.org/x/sys/unix/mksyscall.pl | 0 .../x/sys/unix/mksyscall_solaris.pl | 0 .../golang.org/x/sys/unix/mksysctl_openbsd.pl | 0 .../golang.org/x/sys/unix/mksysnum_darwin.pl | 0 .../x/sys/unix/mksysnum_dragonfly.pl | 0 .../golang.org/x/sys/unix/mksysnum_freebsd.pl | 0 .../golang.org/x/sys/unix/mksysnum_linux.pl | 0 .../golang.org/x/sys/unix/mksysnum_netbsd.pl | 0 .../golang.org/x/sys/unix/mksysnum_openbsd.pl | 0 46 files changed, 1770 insertions(+), 227 deletions(-) create mode 100644 vendor/github.com/vishvananda/netlink/handle_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/mpls_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/order.go create mode 100644 vendor/github.com/vishvananda/netlink/socket.go create mode 100644 vendor/github.com/vishvananda/netlink/socket_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go create mode 100644 vendor/golang.org/x/sys/AUTHORS create mode 100644 vendor/golang.org/x/sys/CONTRIBUTORS mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mkall.sh mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mkerrors.sh mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksyscall.pl mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksyscall_solaris.pl mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksysnum_darwin.pl mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksysnum_linux.pl mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl mode change 100644 => 100755 vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 1c23e4da..62bf3d94 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "github.com/containernetworking/cni", "GoVersion": "go1.6", - "GodepVersion": "v75", + "GodepVersion": "v79", "Packages": [ "./..." ], @@ -39,46 +39,6 @@ "Comment": "v1.2.0-29-g7f8ab55", "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" }, - { - "ImportPath": "github.com/onsi/ginkgo/ginkgo", - "Comment": "v1.2.0-29-g7f8ab55", - "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" - }, - { - "ImportPath": "github.com/onsi/ginkgo/ginkgo/convert", - "Comment": "v1.2.0-29-g7f8ab55", - "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" - }, - { - "ImportPath": "github.com/onsi/ginkgo/ginkgo/interrupthandler", - "Comment": "v1.2.0-29-g7f8ab55", - "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" - }, - { - "ImportPath": "github.com/onsi/ginkgo/ginkgo/nodot", - "Comment": "v1.2.0-29-g7f8ab55", - "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" - }, - { - "ImportPath": "github.com/onsi/ginkgo/ginkgo/testrunner", - "Comment": "v1.2.0-29-g7f8ab55", - "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" - }, - { - "ImportPath": "github.com/onsi/ginkgo/ginkgo/testsuite", - "Comment": "v1.2.0-29-g7f8ab55", - "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" - }, - { - "ImportPath": "github.com/onsi/ginkgo/ginkgo/watch", - "Comment": "v1.2.0-29-g7f8ab55", - "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" - }, - { - "ImportPath": "github.com/onsi/ginkgo/integration", - "Comment": "v1.2.0-29-g7f8ab55", - "Rev": "7f8ab55aaf3b86885aa55b762e803744d1674700" - }, { "ImportPath": "github.com/onsi/ginkgo/internal/codelocation", "Comment": "v1.2.0-29-g7f8ab55", @@ -216,19 +176,19 @@ }, { "ImportPath": "github.com/vishvananda/netlink", - "Rev": "a1f8555521646b5a9800f39c5fd477597697135c" + "Rev": "fe3b5664d23a11b52ba59bece4ff29c52772a56b" }, { "ImportPath": "github.com/vishvananda/netlink/nl", - "Rev": "a1f8555521646b5a9800f39c5fd477597697135c" - }, - { - "ImportPath": "golang.org/x/sys/unix", - "Rev": "076b546753157f758b316e59bcb51e6807c04057" + "Rev": "fe3b5664d23a11b52ba59bece4ff29c52772a56b" }, { "ImportPath": "github.com/vishvananda/netns", "Rev": "8ba1072b58e0c2a240eb5f6120165c7776c3e7b8" + }, + { + "ImportPath": "golang.org/x/sys/unix", + "Rev": "076b546753157f758b316e59bcb51e6807c04057" } ] } diff --git a/vendor/github.com/vishvananda/netlink/Makefile b/vendor/github.com/vishvananda/netlink/Makefile index 8dc5a92e..6c8413b1 100644 --- a/vendor/github.com/vishvananda/netlink/Makefile +++ b/vendor/github.com/vishvananda/netlink/Makefile @@ -21,7 +21,7 @@ $(call testdirs,$(DIRS)): sudo -E go test -test.parallel 4 -timeout 60s -v github.com/vishvananda/netlink/$@ $(call fmt,$(call testdirs,$(DIRS))): - ! gofmt -l $(subst fmt-,,$@)/*.go | grep '' + ! gofmt -l $(subst fmt-,,$@)/*.go | grep -q . .PHONY: fmt fmt: $(call fmt,$(call testdirs,$(DIRS))) diff --git a/vendor/github.com/vishvananda/netlink/addr.go b/vendor/github.com/vishvananda/netlink/addr.go index 079fff3b..fe3e3d36 100644 --- a/vendor/github.com/vishvananda/netlink/addr.go +++ b/vendor/github.com/vishvananda/netlink/addr.go @@ -10,9 +10,11 @@ import ( // include a mask, so it stores the address as a net.IPNet. type Addr struct { *net.IPNet - Label string - Flags int - Scope int + Label string + Flags int + Scope int + Peer *net.IPNet + Broadcast net.IP } // String returns $ip/$netmask $label @@ -43,3 +45,10 @@ func (a Addr) Equal(x Addr) bool { // ignore label for comparison return a.IP.Equal(x.IP) && sizea == sizeb } + +func (a Addr) PeerEqual(x Addr) bool { + sizea, _ := a.Peer.Mask.Size() + sizeb, _ := x.Peer.Mask.Size() + // ignore label for comparison + return a.Peer.IP.Equal(x.Peer.IP) && sizea == sizeb +} diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go index 8820c020..5348e403 100644 --- a/vendor/github.com/vishvananda/netlink/addr_linux.go +++ b/vendor/github.com/vishvananda/netlink/addr_linux.go @@ -56,17 +56,27 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error msg.Prefixlen = uint8(prefixlen) req.AddData(msg) - var addrData []byte + var localAddrData []byte if family == FAMILY_V4 { - addrData = addr.IP.To4() + localAddrData = addr.IP.To4() } else { - addrData = addr.IP.To16() + localAddrData = addr.IP.To16() } - localData := nl.NewRtAttr(syscall.IFA_LOCAL, addrData) + localData := nl.NewRtAttr(syscall.IFA_LOCAL, localAddrData) req.AddData(localData) + var peerAddrData []byte + if addr.Peer != nil { + if family == FAMILY_V4 { + peerAddrData = addr.Peer.IP.To4() + } else { + peerAddrData = addr.Peer.IP.To16() + } + } else { + peerAddrData = localAddrData + } - addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, addrData) + addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, peerAddrData) req.AddData(addressData) if addr.Flags != 0 { @@ -80,6 +90,10 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error } } + if addr.Broadcast != nil { + req.AddData(nl.NewRtAttr(syscall.IFA_BROADCAST, addr.Broadcast)) + } + if addr.Label != "" { labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label)) req.AddData(labelData) @@ -161,11 +175,13 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { IP: attr.Value, Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), } + addr.Peer = dst case syscall.IFA_LOCAL: local = &net.IPNet{ IP: attr.Value, Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), } + addr.IPNet = local case syscall.IFA_LABEL: addr.Label = string(attr.Value[:len(attr.Value)-1]) case IFA_FLAGS: diff --git a/vendor/github.com/vishvananda/netlink/handle_linux.go b/vendor/github.com/vishvananda/netlink/handle_linux.go index 53779887..a04ceae6 100644 --- a/vendor/github.com/vishvananda/netlink/handle_linux.go +++ b/vendor/github.com/vishvananda/netlink/handle_linux.go @@ -1,7 +1,9 @@ package netlink import ( + "fmt" "syscall" + "time" "github.com/vishvananda/netlink/nl" "github.com/vishvananda/netns" @@ -33,6 +35,29 @@ func NewHandle(nlFamilies ...int) (*Handle, error) { return newHandle(netns.None(), netns.None(), nlFamilies...) } +// SetSocketTimeout sets the send and receive timeout for each socket in the +// netlink handle. Although the socket timeout has granularity of one +// microsecond, the effective granularity is floored by the kernel timer tick, +// which default value is four milliseconds. +func (h *Handle) SetSocketTimeout(to time.Duration) error { + if to < time.Microsecond { + return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond) + } + tv := syscall.NsecToTimeval(to.Nanoseconds()) + for _, sh := range h.sockets { + fd := sh.Socket.GetFd() + err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv) + if err != nil { + return err + } + err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv) + if err != nil { + return err + } + } + return nil +} + // NewHandle returns a netlink handle on the network namespace // specified by ns. If ns=netns.None(), current network namespace // will be assumed diff --git a/vendor/github.com/vishvananda/netlink/handle_unspecified.go b/vendor/github.com/vishvananda/netlink/handle_unspecified.go new file mode 100644 index 00000000..32cf0227 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/handle_unspecified.go @@ -0,0 +1,218 @@ +// +build !linux + +package netlink + +import ( + "net" + "time" + + "github.com/vishvananda/netns" +) + +type Handle struct{} + +func NewHandle(nlFamilies ...int) (*Handle, error) { + return nil, ErrNotImplemented +} + +func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) { + return nil, ErrNotImplemented +} + +func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) Delete() {} + +func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool { + return false +} + +func (h *Handle) SetSocketTimeout(to time.Duration) error { + return ErrNotImplemented +} + +func (h *Handle) SetPromiscOn(link Link) error { + return ErrNotImplemented +} + +func (h *Handle) SetPromiscOff(link Link) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetUp(link Link) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetDown(link Link) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetMTU(link Link, mtu int) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetName(link Link, name string) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetAlias(link Link, name string) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetMaster(link Link, master *Bridge) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetNoMaster(link Link) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetMasterByIndex(link Link, masterIndex int) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetNsPid(link Link, nspid int) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetNsFd(link Link, fd int) error { + return ErrNotImplemented +} + +func (h *Handle) LinkAdd(link Link) error { + return ErrNotImplemented +} + +func (h *Handle) LinkDel(link Link) error { + return ErrNotImplemented +} + +func (h *Handle) LinkByName(name string) (Link, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) LinkByAlias(alias string) (Link, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) LinkByIndex(index int) (Link, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) LinkList() ([]Link, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) LinkSetHairpin(link Link, mode bool) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetGuard(link Link, mode bool) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetFastLeave(link Link, mode bool) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetLearning(link Link, mode bool) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetRootBlock(link Link, mode bool) error { + return ErrNotImplemented +} + +func (h *Handle) LinkSetFlood(link Link, mode bool) error { + return ErrNotImplemented +} + +func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { + return ErrNotImplemented +} + +func (h *Handle) AddrAdd(link Link, addr *Addr) error { + return ErrNotImplemented +} + +func (h *Handle) AddrDel(link Link, addr *Addr) error { + return ErrNotImplemented +} + +func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) ClassDel(class Class) error { + return ErrNotImplemented +} + +func (h *Handle) ClassChange(class Class) error { + return ErrNotImplemented +} + +func (h *Handle) ClassReplace(class Class) error { + return ErrNotImplemented +} + +func (h *Handle) ClassAdd(class Class) error { + return ErrNotImplemented +} + +func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) FilterDel(filter Filter) error { + return ErrNotImplemented +} + +func (h *Handle) FilterAdd(filter Filter) error { + return ErrNotImplemented +} + +func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) NeighAdd(neigh *Neigh) error { + return ErrNotImplemented +} + +func (h *Handle) NeighSet(neigh *Neigh) error { + return ErrNotImplemented +} + +func (h *Handle) NeighAppend(neigh *Neigh) error { + return ErrNotImplemented +} + +func (h *Handle) NeighDel(neigh *Neigh) error { + return ErrNotImplemented +} + +func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { + return nil, ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go index 0e160a9f..924211cd 100644 --- a/vendor/github.com/vishvananda/netlink/link.go +++ b/vendor/github.com/vishvananda/netlink/link.go @@ -35,6 +35,41 @@ type LinkAttrs struct { Promisc int Xdp *LinkXdp EncapType string + Protinfo *Protinfo + OperState LinkOperState +} + +// LinkOperState represents the values of the IFLA_OPERSTATE link +// attribute, which contains the RFC2863 state of the interface. +type LinkOperState uint8 + +const ( + OperUnknown = iota // Status can't be determined. + OperNotPresent // Some component is missing. + OperDown // Down. + OperLowerLayerDown // Down due to state of lower layer. + OperTesting // In some test mode. + OperDormant // Not up but pending an external event. + OperUp // Up, ready to send packets. +) + +func (s LinkOperState) String() string { + switch s { + case OperNotPresent: + return "not-present" + case OperDown: + return "down" + case OperLowerLayerDown: + return "lower-layer-down" + case OperTesting: + return "testing" + case OperDormant: + return "dormant" + case OperUp: + return "up" + default: + return "unknown" + } } // NewLinkAttrs returns LinkAttrs structure filled with default values @@ -44,10 +79,12 @@ func NewLinkAttrs() LinkAttrs { } } +type LinkStatistics LinkStatistics64 + /* Ref: struct rtnl_link_stats {...} */ -type LinkStatistics struct { +type LinkStatistics32 struct { RxPackets uint32 TxPackets uint32 RxBytes uint32 @@ -73,6 +110,63 @@ type LinkStatistics struct { TxCompressed uint32 } +func (s32 LinkStatistics32) to64() *LinkStatistics64 { + return &LinkStatistics64{ + RxPackets: uint64(s32.RxPackets), + TxPackets: uint64(s32.TxPackets), + RxBytes: uint64(s32.RxBytes), + TxBytes: uint64(s32.TxBytes), + RxErrors: uint64(s32.RxErrors), + TxErrors: uint64(s32.TxErrors), + RxDropped: uint64(s32.RxDropped), + TxDropped: uint64(s32.TxDropped), + Multicast: uint64(s32.Multicast), + Collisions: uint64(s32.Collisions), + RxLengthErrors: uint64(s32.RxLengthErrors), + RxOverErrors: uint64(s32.RxOverErrors), + RxCrcErrors: uint64(s32.RxCrcErrors), + RxFrameErrors: uint64(s32.RxFrameErrors), + RxFifoErrors: uint64(s32.RxFifoErrors), + RxMissedErrors: uint64(s32.RxMissedErrors), + TxAbortedErrors: uint64(s32.TxAbortedErrors), + TxCarrierErrors: uint64(s32.TxCarrierErrors), + TxFifoErrors: uint64(s32.TxFifoErrors), + TxHeartbeatErrors: uint64(s32.TxHeartbeatErrors), + TxWindowErrors: uint64(s32.TxWindowErrors), + RxCompressed: uint64(s32.RxCompressed), + TxCompressed: uint64(s32.TxCompressed), + } +} + +/* +Ref: struct rtnl_link_stats64 {...} +*/ +type LinkStatistics64 struct { + RxPackets uint64 + TxPackets uint64 + RxBytes uint64 + TxBytes uint64 + RxErrors uint64 + TxErrors uint64 + RxDropped uint64 + TxDropped uint64 + Multicast uint64 + Collisions uint64 + RxLengthErrors uint64 + RxOverErrors uint64 + RxCrcErrors uint64 + RxFrameErrors uint64 + RxFifoErrors uint64 + RxMissedErrors uint64 + TxAbortedErrors uint64 + TxCarrierErrors uint64 + TxFifoErrors uint64 + TxHeartbeatErrors uint64 + TxWindowErrors uint64 + RxCompressed uint64 + TxCompressed uint64 +} + type LinkXdp struct { Fd int Attached bool @@ -301,31 +395,31 @@ func StringToBondMode(s string) BondMode { // Possible BondMode const ( - BOND_MODE_802_3AD BondMode = iota - BOND_MODE_BALANCE_RR + BOND_MODE_BALANCE_RR BondMode = iota BOND_MODE_ACTIVE_BACKUP BOND_MODE_BALANCE_XOR BOND_MODE_BROADCAST + BOND_MODE_802_3AD BOND_MODE_BALANCE_TLB BOND_MODE_BALANCE_ALB BOND_MODE_UNKNOWN ) var bondModeToString = map[BondMode]string{ - BOND_MODE_802_3AD: "802.3ad", BOND_MODE_BALANCE_RR: "balance-rr", BOND_MODE_ACTIVE_BACKUP: "active-backup", BOND_MODE_BALANCE_XOR: "balance-xor", BOND_MODE_BROADCAST: "broadcast", + BOND_MODE_802_3AD: "802.3ad", BOND_MODE_BALANCE_TLB: "balance-tlb", BOND_MODE_BALANCE_ALB: "balance-alb", } var StringToBondModeMap = map[string]BondMode{ - "802.3ad": BOND_MODE_802_3AD, "balance-rr": BOND_MODE_BALANCE_RR, "active-backup": BOND_MODE_ACTIVE_BACKUP, "balance-xor": BOND_MODE_BALANCE_XOR, "broadcast": BOND_MODE_BROADCAST, + "802.3ad": BOND_MODE_802_3AD, "balance-tlb": BOND_MODE_BALANCE_TLB, "balance-alb": BOND_MODE_BALANCE_ALB, } @@ -589,6 +683,54 @@ func (gretap *Gretap) Type() string { return "gretap" } +type Iptun struct { + LinkAttrs + Ttl uint8 + Tos uint8 + PMtuDisc uint8 + Link uint32 + Local net.IP + Remote net.IP +} + +func (iptun *Iptun) Attrs() *LinkAttrs { + return &iptun.LinkAttrs +} + +func (iptun *Iptun) Type() string { + return "ipip" +} + +type Vti struct { + LinkAttrs + IKey uint32 + OKey uint32 + Link uint32 + Local net.IP + Remote net.IP +} + +func (vti *Vti) Attrs() *LinkAttrs { + return &vti.LinkAttrs +} + +func (iptun *Vti) Type() string { + return "vti" +} + +type Vrf struct { + LinkAttrs + Table uint32 +} + +func (vrf *Vrf) Attrs() *LinkAttrs { + return &vrf.LinkAttrs +} + +func (vrf *Vrf) Type() string { + return "vrf" +} + // iproute2 supported devices; // vlan | veth | vcan | dummy | ifb | macvlan | macvtap | // bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go index 9088b888..56409eb2 100644 --- a/vendor/github.com/vishvananda/netlink/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/link_linux.go @@ -13,7 +13,11 @@ import ( "github.com/vishvananda/netns" ) -const SizeofLinkStats = 0x5c +const ( + SizeofLinkStats32 = 0x5c + SizeofLinkStats64 = 0xd8 + IFLA_STATS64 = 0x17 // syscall pkg does not contain this one +) const ( TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN @@ -25,7 +29,6 @@ const ( TUNTAP_ONE_QUEUE TuntapFlag = syscall.IFF_ONE_QUEUE ) -var native = nl.NativeEndian() var lookupByDump = false var macvlanModes = [...]uint32{ @@ -298,6 +301,36 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error { return err } +// LinkSetVfTxRate sets the tx rate of a vf for the link. +// Equivalent to: `ip link set $link vf $vf rate $rate` +func LinkSetVfTxRate(link Link, vf, rate int) error { + return pkgHandle.LinkSetVfTxRate(link, vf, rate) +} + +// LinkSetVfTxRate sets the tx rate of a vf for the link. +// Equivalent to: `ip link set $link vf $vf rate $rate` +func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK) + + msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil) + info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil) + vfmsg := nl.VfTxRate{ + Vf: uint32(vf), + Rate: uint32(rate), + } + nl.NewRtAttrChild(info, nl.IFLA_VF_TX_RATE, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + // LinkSetMaster sets the master of the link device. // Equivalent to: `ip link set $link master $master` func LinkSetMaster(link Link, master *Bridge) error { @@ -753,6 +786,12 @@ func (h *Handle) LinkAdd(link Link) error { } } else if gretap, ok := link.(*Gretap); ok { addGretapAttrs(gretap, linkInfo) + } else if iptun, ok := link.(*Iptun); ok { + addIptunAttrs(iptun, linkInfo) + } else if vti, ok := link.(*Vti); ok { + addVtiAttrs(vti, linkInfo) + } else if vrf, ok := link.(*Vrf); ok { + addVrfAttrs(vrf, linkInfo) } req.AddData(linkInfo) @@ -919,7 +958,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) { return nil, fmt.Errorf("Link not found") case len(msgs) == 1: - return linkDeserialize(msgs[0]) + return LinkDeserialize(nil, msgs[0]) default: return nil, fmt.Errorf("More than one link found") @@ -928,7 +967,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) { // linkDeserialize deserializes a raw message received from netlink into // a link object. -func linkDeserialize(m []byte) (Link, error) { +func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) { msg := nl.DeserializeIfInfomsg(m) attrs, err := nl.ParseRouteAttr(m[msg.Len():]) @@ -940,8 +979,12 @@ func linkDeserialize(m []byte) (Link, error) { if msg.Flags&syscall.IFF_PROMISC != 0 { base.Promisc = 1 } - var link Link - linkType := "" + var ( + link Link + stats32 []byte + stats64 []byte + linkType string + ) for _, attr := range attrs { switch attr.Attr.Type { case syscall.IFLA_LINKINFO: @@ -976,6 +1019,12 @@ func linkDeserialize(m []byte) (Link, error) { link = &Macvtap{} case "gretap": link = &Gretap{} + case "ipip": + link = &Iptun{} + case "vti": + link = &Vti{} + case "vrf": + link = &Vrf{} default: link = &GenericLink{LinkType: linkType} } @@ -999,6 +1048,12 @@ func linkDeserialize(m []byte) (Link, error) { parseMacvtapData(link, data) case "gretap": parseGretapData(link, data) + case "ipip": + parseIptunData(link, data) + case "vti": + parseVtiData(link, data) + case "vrf": + parseVrfData(link, data) } } } @@ -1025,15 +1080,35 @@ func linkDeserialize(m []byte) (Link, error) { case syscall.IFLA_IFALIAS: base.Alias = string(attr.Value[:len(attr.Value)-1]) case syscall.IFLA_STATS: - base.Statistics = parseLinkStats(attr.Value[:]) + stats32 = attr.Value[:] + case IFLA_STATS64: + stats64 = attr.Value[:] case nl.IFLA_XDP: xdp, err := parseLinkXdp(attr.Value[:]) if err != nil { return nil, err } base.Xdp = xdp + case syscall.IFLA_PROTINFO | syscall.NLA_F_NESTED: + if hdr != nil && hdr.Type == syscall.RTM_NEWLINK && + msg.Family == syscall.AF_BRIDGE { + attrs, err := nl.ParseRouteAttr(attr.Value[:]) + if err != nil { + return nil, err + } + base.Protinfo = parseProtinfo(attrs) + } + case syscall.IFLA_OPERSTATE: + base.OperState = LinkOperState(uint8(attr.Value[0])) } } + + if stats64 != nil { + base.Statistics = parseLinkStats64(stats64) + } else if stats32 != nil { + base.Statistics = parseLinkStats32(stats32) + } + // Links that don't have IFLA_INFO_KIND are hardware devices if link == nil { link = &Device{} @@ -1066,7 +1141,7 @@ func (h *Handle) LinkList() ([]Link, error) { var res []Link for _, m := range msgs { - link, err := linkDeserialize(m) + link, err := LinkDeserialize(nil, m) if err != nil { return nil, err } @@ -1115,7 +1190,7 @@ func linkSubscribe(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-cha } for _, m := range msgs { ifmsg := nl.DeserializeIfInfomsg(m.Data) - link, err := linkDeserialize(m.Data) + link, err := LinkDeserialize(&m.Header, m.Data) if err != nil { return } @@ -1367,26 +1442,6 @@ func linkFlags(rawFlags uint32) net.Flags { return f } -func htonl(val uint32) []byte { - bytes := make([]byte, 4) - binary.BigEndian.PutUint32(bytes, val) - return bytes -} - -func htons(val uint16) []byte { - bytes := make([]byte, 2) - binary.BigEndian.PutUint16(bytes, val) - return bytes -} - -func ntohl(buf []byte) uint32 { - return binary.BigEndian.Uint32(buf) -} - -func ntohs(buf []byte) uint16 { - return binary.BigEndian.Uint16(buf) -} - func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) { data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) @@ -1460,8 +1515,12 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) { } } -func parseLinkStats(data []byte) *LinkStatistics { - return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0])) +func parseLinkStats32(data []byte) *LinkStatistics { + return (*LinkStatistics)((*LinkStatistics32)(unsafe.Pointer(&data[0:SizeofLinkStats32][0])).to64()) +} + +func parseLinkStats64(data []byte) *LinkStatistics { + return (*LinkStatistics)((*LinkStatistics64)(unsafe.Pointer(&data[0:SizeofLinkStats64][0]))) } func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) { @@ -1488,3 +1547,96 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) { } return xdp, nil } + +func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) { + data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + + ip := iptun.Local.To4() + if ip != nil { + nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LOCAL, []byte(ip)) + } + + ip = iptun.Remote.To4() + if ip != nil { + nl.NewRtAttrChild(data, nl.IFLA_IPTUN_REMOTE, []byte(ip)) + } + + if iptun.Link != 0 { + nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link)) + } + nl.NewRtAttrChild(data, nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc)) + nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl)) + nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos)) +} + +func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) { + iptun := link.(*Iptun) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_IPTUN_LOCAL: + iptun.Local = net.IP(datum.Value[0:4]) + case nl.IFLA_IPTUN_REMOTE: + iptun.Remote = net.IP(datum.Value[0:4]) + case nl.IFLA_IPTUN_TTL: + iptun.Ttl = uint8(datum.Value[0]) + case nl.IFLA_IPTUN_TOS: + iptun.Tos = uint8(datum.Value[0]) + case nl.IFLA_IPTUN_PMTUDISC: + iptun.PMtuDisc = uint8(datum.Value[0]) + } + } +} + +func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) { + data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + + ip := vti.Local.To4() + if ip != nil { + nl.NewRtAttrChild(data, nl.IFLA_VTI_LOCAL, []byte(ip)) + } + + ip = vti.Remote.To4() + if ip != nil { + nl.NewRtAttrChild(data, nl.IFLA_VTI_REMOTE, []byte(ip)) + } + + if vti.Link != 0 { + nl.NewRtAttrChild(data, nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link)) + } + + nl.NewRtAttrChild(data, nl.IFLA_VTI_IKEY, htonl(vti.IKey)) + nl.NewRtAttrChild(data, nl.IFLA_VTI_OKEY, htonl(vti.OKey)) +} + +func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) { + vti := link.(*Vti) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_VTI_LOCAL: + vti.Local = net.IP(datum.Value[0:4]) + case nl.IFLA_VTI_REMOTE: + vti.Remote = net.IP(datum.Value[0:4]) + case nl.IFLA_VTI_IKEY: + vti.IKey = ntohl(datum.Value[0:4]) + case nl.IFLA_VTI_OKEY: + vti.OKey = ntohl(datum.Value[0:4]) + } + } +} + +func addVrfAttrs(vrf *Vrf, linkInfo *nl.RtAttr) { + data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + b := make([]byte, 4) + native.PutUint32(b, uint32(vrf.Table)) + nl.NewRtAttrChild(data, nl.IFLA_VRF_TABLE, b) +} + +func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) { + vrf := link.(*Vrf) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_VRF_TABLE: + vrf.Table = native.Uint32(datum.Value[0:4]) + } + } +} diff --git a/vendor/github.com/vishvananda/netlink/netlink.go b/vendor/github.com/vishvananda/netlink/netlink.go index d8e02f47..fb159526 100644 --- a/vendor/github.com/vishvananda/netlink/netlink.go +++ b/vendor/github.com/vishvananda/netlink/netlink.go @@ -8,7 +8,15 @@ // interface that is loosly modeled on the iproute2 cli. package netlink -import "net" +import ( + "errors" + "net" +) + +var ( + // ErrNotImplemented is returned when a requested feature is not implemented. + ErrNotImplemented = errors.New("not implemented") +) // ParseIPNet parses a string in ip/net format and returns a net.IPNet. // This is valuable because addresses in netlink are often IPNets and diff --git a/vendor/github.com/vishvananda/netlink/netlink_linux.go b/vendor/github.com/vishvananda/netlink/netlink_linux.go index 32d8537e..a20d293d 100644 --- a/vendor/github.com/vishvananda/netlink/netlink_linux.go +++ b/vendor/github.com/vishvananda/netlink/netlink_linux.go @@ -4,7 +4,8 @@ import "github.com/vishvananda/netlink/nl" // Family type definitions const ( - FAMILY_ALL = nl.FAMILY_ALL - FAMILY_V4 = nl.FAMILY_V4 - FAMILY_V6 = nl.FAMILY_V6 + FAMILY_ALL = nl.FAMILY_ALL + FAMILY_V4 = nl.FAMILY_V4 + FAMILY_V6 = nl.FAMILY_V6 + FAMILY_MPLS = nl.FAMILY_MPLS ) diff --git a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go index 9ad7a628..fa421e4e 100644 --- a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go +++ b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go @@ -2,43 +2,109 @@ package netlink -import ( - "errors" -) +import "net" -var ( - ErrNotImplemented = errors.New("not implemented") -) +func LinkSetUp(link Link) error { + return ErrNotImplemented +} + +func LinkSetDown(link Link) error { + return ErrNotImplemented +} + +func LinkSetMTU(link Link, mtu int) error { + return ErrNotImplemented +} + +func LinkSetMaster(link Link, master *Link) error { + return ErrNotImplemented +} + +func LinkSetNsPid(link Link, nspid int) error { + return ErrNotImplemented +} + +func LinkSetNsFd(link Link, fd int) error { + return ErrNotImplemented +} + +func LinkSetName(link Link, name string) error { + return ErrNotImplemented +} + +func LinkSetAlias(link Link, name string) error { + return ErrNotImplemented +} + +func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { + return ErrNotImplemented +} + +func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { + return ErrNotImplemented +} + +func LinkSetVfVlan(link Link, vf, vlan int) error { + return ErrNotImplemented +} + +func LinkSetVfTxRate(link Link, vf, rate int) error { + return ErrNotImplemented +} + +func LinkSetNoMaster(link Link) error { + return ErrNotImplemented +} + +func LinkSetMasterByIndex(link Link, masterIndex int) error { + return ErrNotImplemented +} + +func LinkSetXdpFd(link Link, fd int) error { + return ErrNotImplemented +} + +func LinkByName(name string) (Link, error) { + return nil, ErrNotImplemented +} + +func LinkByAlias(alias string) (Link, error) { + return nil, ErrNotImplemented +} + +func LinkByIndex(index int) (Link, error) { + return nil, ErrNotImplemented +} -func LinkSetUp(link *Link) error { +func LinkSetHairpin(link Link, mode bool) error { return ErrNotImplemented } -func LinkSetDown(link *Link) error { +func LinkSetGuard(link Link, mode bool) error { return ErrNotImplemented } -func LinkSetMTU(link *Link, mtu int) error { +func LinkSetFastLeave(link Link, mode bool) error { return ErrNotImplemented } -func LinkSetMaster(link *Link, master *Link) error { +func LinkSetLearning(link Link, mode bool) error { return ErrNotImplemented } -func LinkSetNsPid(link *Link, nspid int) error { +func LinkSetRootBlock(link Link, mode bool) error { return ErrNotImplemented } -func LinkSetNsFd(link *Link, fd int) error { +func LinkSetFlood(link Link, mode bool) error { return ErrNotImplemented } -func LinkAdd(link *Link) error { +func LinkAdd(link Link) error { return ErrNotImplemented } -func LinkDel(link *Link) error { +func LinkDel(link Link) error { return ErrNotImplemented } @@ -70,15 +136,15 @@ func LinkList() ([]Link, error) { return nil, ErrNotImplemented } -func AddrAdd(link *Link, addr *Addr) error { +func AddrAdd(link Link, addr *Addr) error { return ErrNotImplemented } -func AddrDel(link *Link, addr *Addr) error { +func AddrDel(link Link, addr *Addr) error { return ErrNotImplemented } -func AddrList(link *Link, family int) ([]Addr, error) { +func AddrList(link Link, family int) ([]Addr, error) { return nil, ErrNotImplemented } @@ -90,7 +156,7 @@ func RouteDel(route *Route) error { return ErrNotImplemented } -func RouteList(link *Link, family int) ([]Route, error) { +func RouteList(link Link, family int) ([]Route, error) { return nil, ErrNotImplemented } @@ -141,3 +207,7 @@ func NeighList(linkIndex, family int) ([]Neigh, error) { func NeighDeserialize(m []byte) (*Neigh, error) { return nil, ErrNotImplemented } + +func SocketGet(local, remote net.Addr) (*Socket, error) { + return nil, ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go index 115f60bb..6d9af569 100644 --- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go @@ -418,3 +418,37 @@ const ( IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */ IFLA_XDP_MAX = IFLA_XDP_ATTACHED ) + +const ( + IFLA_IPTUN_UNSPEC = iota + IFLA_IPTUN_LINK + IFLA_IPTUN_LOCAL + IFLA_IPTUN_REMOTE + IFLA_IPTUN_TTL + IFLA_IPTUN_TOS + IFLA_IPTUN_ENCAP_LIMIT + IFLA_IPTUN_FLOWINFO + IFLA_IPTUN_FLAGS + IFLA_IPTUN_PROTO + IFLA_IPTUN_PMTUDISC + IFLA_IPTUN_6RD_PREFIX + IFLA_IPTUN_6RD_RELAY_PREFIX + IFLA_IPTUN_6RD_PREFIXLEN + IFLA_IPTUN_6RD_RELAY_PREFIXLEN + IFLA_IPTUN_MAX = IFLA_IPTUN_6RD_RELAY_PREFIXLEN +) + +const ( + IFLA_VTI_UNSPEC = iota + IFLA_VTI_LINK + IFLA_VTI_IKEY + IFLA_VTI_OKEY + IFLA_VTI_LOCAL + IFLA_VTI_REMOTE + IFLA_VTI_MAX = IFLA_VTI_REMOTE +) + +const ( + IFLA_VRF_UNSPEC = iota + IFLA_VRF_TABLE +) diff --git a/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go b/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go new file mode 100644 index 00000000..3915b7ee --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go @@ -0,0 +1,36 @@ +package nl + +import "encoding/binary" + +const ( + MPLS_LS_LABEL_SHIFT = 12 + MPLS_LS_S_SHIFT = 8 +) + +func EncodeMPLSStack(labels ...int) []byte { + b := make([]byte, 4*len(labels)) + for idx, label := range labels { + l := label << MPLS_LS_LABEL_SHIFT + if idx == len(labels)-1 { + l |= 1 << MPLS_LS_S_SHIFT + } + binary.BigEndian.PutUint32(b[idx*4:], uint32(l)) + } + return b +} + +func DecodeMPLSStack(buf []byte) []int { + if len(buf)%4 != 0 { + return nil + } + stack := make([]int, 0, len(buf)/4) + for len(buf) > 0 { + l := binary.BigEndian.Uint32(buf[:4]) + buf = buf[4:] + stack = append(stack, int(l)>>MPLS_LS_LABEL_SHIFT) + if (l>>MPLS_LS_S_SHIFT)&1 > 0 { + break + } + } + return stack +} diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go index d46fff28..fb9031e3 100644 --- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go @@ -17,9 +17,10 @@ import ( const ( // Family type definitions - FAMILY_ALL = syscall.AF_UNSPEC - FAMILY_V4 = syscall.AF_INET - FAMILY_V6 = syscall.AF_INET6 + FAMILY_ALL = syscall.AF_UNSPEC + FAMILY_V4 = syscall.AF_INET + FAMILY_V6 = syscall.AF_INET6 + FAMILY_MPLS = AF_MPLS ) // SupportedNlFamilies contains the list of netlink families this netlink package supports @@ -656,6 +657,13 @@ func Uint32Attr(v uint32) []byte { return bytes } +func Uint64Attr(v uint64) []byte { + native := NativeEndian() + bytes := make([]byte, 8) + native.PutUint64(bytes, v) + return bytes +} + func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) { var attrs []syscall.NetlinkRouteAttr for len(b) >= syscall.SizeofRtAttr { diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go b/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go new file mode 100644 index 00000000..dfc0be66 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go @@ -0,0 +1,11 @@ +// +build !linux + +package nl + +import "encoding/binary" + +var SupportedNlFamilies = []int{} + +func NativeEndian() binary.ByteOrder { + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/nl/route_linux.go b/vendor/github.com/vishvananda/netlink/nl/route_linux.go index f7db88df..1a064d65 100644 --- a/vendor/github.com/vishvananda/netlink/nl/route_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/route_linux.go @@ -43,12 +43,38 @@ func (msg *RtMsg) Serialize() []byte { type RtNexthop struct { syscall.RtNexthop + Children []NetlinkRequestData } func DeserializeRtNexthop(b []byte) *RtNexthop { return (*RtNexthop)(unsafe.Pointer(&b[0:syscall.SizeofRtNexthop][0])) } +func (msg *RtNexthop) Len() int { + if len(msg.Children) == 0 { + return syscall.SizeofRtNexthop + } + + l := 0 + for _, child := range msg.Children { + l += rtaAlignOf(child.Len()) + } + l += syscall.SizeofRtNexthop + return rtaAlignOf(l) +} + func (msg *RtNexthop) Serialize() []byte { - return (*(*[syscall.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:] + length := msg.Len() + msg.RtNexthop.Len = uint16(length) + buf := make([]byte, length) + copy(buf, (*(*[syscall.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:]) + next := rtaAlignOf(syscall.SizeofRtNexthop) + if len(msg.Children) > 0 { + for _, child := range msg.Children { + childBuf := child.Serialize() + copy(buf[next:], childBuf) + next += rtaAlignOf(len(childBuf)) + } + } + return buf } diff --git a/vendor/github.com/vishvananda/netlink/nl/syscall.go b/vendor/github.com/vishvananda/netlink/nl/syscall.go index 47aa6322..3473e536 100644 --- a/vendor/github.com/vishvananda/netlink/nl/syscall.go +++ b/vendor/github.com/vishvananda/netlink/nl/syscall.go @@ -35,3 +35,34 @@ const ( FR_ACT_UNREACHABLE /* Drop with ENETUNREACH */ FR_ACT_PROHIBIT /* Drop with EACCES */ ) + +// socket diags related +const ( + SOCK_DIAG_BY_FAMILY = 20 /* linux.sock_diag.h */ + TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/ +) + +const ( + AF_MPLS = 28 +) + +const ( + RTA_NEWDST = 0x13 + RTA_ENCAP_TYPE = 0x15 + RTA_ENCAP = 0x16 +) + +// RTA_ENCAP subtype +const ( + MPLS_IPTUNNEL_UNSPEC = iota + MPLS_IPTUNNEL_DST +) + +// light weight tunnel encap types +const ( + LWTUNNEL_ENCAP_NONE = iota + LWTUNNEL_ENCAP_MPLS + LWTUNNEL_ENCAP_IP + LWTUNNEL_ENCAP_ILA + LWTUNNEL_ENCAP_IP6 +) diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go index ebf47946..09a2ffa1 100644 --- a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go @@ -11,34 +11,40 @@ const ( XFRM_INF = ^uint64(0) ) +type XfrmMsgType uint8 + +type XfrmMsg interface { + Type() XfrmMsgType +} + // Message Types const ( - XFRM_MSG_BASE = 0x10 - XFRM_MSG_NEWSA = 0x10 - XFRM_MSG_DELSA = 0x11 - XFRM_MSG_GETSA = 0x12 - XFRM_MSG_NEWPOLICY = 0x13 - XFRM_MSG_DELPOLICY = 0x14 - XFRM_MSG_GETPOLICY = 0x15 - XFRM_MSG_ALLOCSPI = 0x16 - XFRM_MSG_ACQUIRE = 0x17 - XFRM_MSG_EXPIRE = 0x18 - XFRM_MSG_UPDPOLICY = 0x19 - XFRM_MSG_UPDSA = 0x1a - XFRM_MSG_POLEXPIRE = 0x1b - XFRM_MSG_FLUSHSA = 0x1c - XFRM_MSG_FLUSHPOLICY = 0x1d - XFRM_MSG_NEWAE = 0x1e - XFRM_MSG_GETAE = 0x1f - XFRM_MSG_REPORT = 0x20 - XFRM_MSG_MIGRATE = 0x21 - XFRM_MSG_NEWSADINFO = 0x22 - XFRM_MSG_GETSADINFO = 0x23 - XFRM_MSG_NEWSPDINFO = 0x24 - XFRM_MSG_GETSPDINFO = 0x25 - XFRM_MSG_MAPPING = 0x26 - XFRM_MSG_MAX = 0x26 - XFRM_NR_MSGTYPES = 0x17 + XFRM_MSG_BASE XfrmMsgType = 0x10 + XFRM_MSG_NEWSA = 0x10 + XFRM_MSG_DELSA = 0x11 + XFRM_MSG_GETSA = 0x12 + XFRM_MSG_NEWPOLICY = 0x13 + XFRM_MSG_DELPOLICY = 0x14 + XFRM_MSG_GETPOLICY = 0x15 + XFRM_MSG_ALLOCSPI = 0x16 + XFRM_MSG_ACQUIRE = 0x17 + XFRM_MSG_EXPIRE = 0x18 + XFRM_MSG_UPDPOLICY = 0x19 + XFRM_MSG_UPDSA = 0x1a + XFRM_MSG_POLEXPIRE = 0x1b + XFRM_MSG_FLUSHSA = 0x1c + XFRM_MSG_FLUSHPOLICY = 0x1d + XFRM_MSG_NEWAE = 0x1e + XFRM_MSG_GETAE = 0x1f + XFRM_MSG_REPORT = 0x20 + XFRM_MSG_MIGRATE = 0x21 + XFRM_MSG_NEWSADINFO = 0x22 + XFRM_MSG_GETSADINFO = 0x23 + XFRM_MSG_NEWSPDINFO = 0x24 + XFRM_MSG_GETSPDINFO = 0x25 + XFRM_MSG_MAPPING = 0x26 + XFRM_MSG_MAX = 0x26 + XFRM_NR_MSGTYPES = 0x17 ) // Attribute types @@ -81,6 +87,20 @@ const ( SizeofXfrmMark = 0x08 ) +// Netlink groups +const ( + XFRMNLGRP_NONE = 0x0 + XFRMNLGRP_ACQUIRE = 0x1 + XFRMNLGRP_EXPIRE = 0x2 + XFRMNLGRP_SA = 0x3 + XFRMNLGRP_POLICY = 0x4 + XFRMNLGRP_AEVENTS = 0x5 + XFRMNLGRP_REPORT = 0x6 + XFRMNLGRP_MIGRATE = 0x7 + XFRMNLGRP_MAPPING = 0x8 + __XFRMNLGRP_MAX = 0x9 +) + // typedef union { // __be32 a4; // __be32 a6[4]; diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go new file mode 100644 index 00000000..715df4cc --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go @@ -0,0 +1,32 @@ +package nl + +import ( + "unsafe" +) + +const ( + SizeofXfrmUserExpire = 0xe8 +) + +// struct xfrm_user_expire { +// struct xfrm_usersa_info state; +// __u8 hard; +// }; + +type XfrmUserExpire struct { + XfrmUsersaInfo XfrmUsersaInfo + Hard uint8 + Pad [7]byte +} + +func (msg *XfrmUserExpire) Len() int { + return SizeofXfrmUserExpire +} + +func DeserializeXfrmUserExpire(b []byte) *XfrmUserExpire { + return (*XfrmUserExpire)(unsafe.Pointer(&b[0:SizeofXfrmUserExpire][0])) +} + +func (msg *XfrmUserExpire) Serialize() []byte { + return (*(*[SizeofXfrmUserExpire]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go index 856db3da..b6290fd5 100644 --- a/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go @@ -5,14 +5,27 @@ import ( ) const ( - SizeofXfrmUsersaId = 0x18 - SizeofXfrmStats = 0x0c - SizeofXfrmUsersaInfo = 0xe0 - SizeofXfrmAlgo = 0x44 - SizeofXfrmAlgoAuth = 0x48 - SizeofXfrmAlgoAEAD = 0x48 - SizeofXfrmEncapTmpl = 0x18 - SizeofXfrmUsersaFlush = 0x8 + SizeofXfrmUsersaId = 0x18 + SizeofXfrmStats = 0x0c + SizeofXfrmUsersaInfo = 0xe0 + SizeofXfrmUserSpiInfo = 0xe8 + SizeofXfrmAlgo = 0x44 + SizeofXfrmAlgoAuth = 0x48 + SizeofXfrmAlgoAEAD = 0x48 + SizeofXfrmEncapTmpl = 0x18 + SizeofXfrmUsersaFlush = 0x8 + SizeofXfrmReplayStateEsn = 0x18 +) + +const ( + XFRM_STATE_NOECN = 1 + XFRM_STATE_DECAP_DSCP = 2 + XFRM_STATE_NOPMTUDISC = 4 + XFRM_STATE_WILDRECV = 8 + XFRM_STATE_ICMP = 16 + XFRM_STATE_AF_UNSPEC = 32 + XFRM_STATE_ALIGN4 = 64 + XFRM_STATE_ESN = 128 ) // struct xfrm_usersa_id { @@ -120,6 +133,30 @@ func (msg *XfrmUsersaInfo) Serialize() []byte { return (*(*[SizeofXfrmUsersaInfo]byte)(unsafe.Pointer(msg)))[:] } +// struct xfrm_userspi_info { +// struct xfrm_usersa_info info; +// __u32 min; +// __u32 max; +// }; + +type XfrmUserSpiInfo struct { + XfrmUsersaInfo XfrmUsersaInfo + Min uint32 + Max uint32 +} + +func (msg *XfrmUserSpiInfo) Len() int { + return SizeofXfrmUserSpiInfo +} + +func DeserializeXfrmUserSpiInfo(b []byte) *XfrmUserSpiInfo { + return (*XfrmUserSpiInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserSpiInfo][0])) +} + +func (msg *XfrmUserSpiInfo) Serialize() []byte { + return (*(*[SizeofXfrmUserSpiInfo]byte)(unsafe.Pointer(msg)))[:] +} + // struct xfrm_algo { // char alg_name[64]; // unsigned int alg_key_len; /* in bits */ @@ -270,3 +307,28 @@ func DeserializeXfrmUsersaFlush(b []byte) *XfrmUsersaFlush { func (msg *XfrmUsersaFlush) Serialize() []byte { return (*(*[SizeofXfrmUsersaFlush]byte)(unsafe.Pointer(msg)))[:] } + +// struct xfrm_replay_state_esn { +// unsigned int bmp_len; +// __u32 oseq; +// __u32 seq; +// __u32 oseq_hi; +// __u32 seq_hi; +// __u32 replay_window; +// __u32 bmp[0]; +// }; + +type XfrmReplayStateEsn struct { + BmpLen uint32 + OSeq uint32 + Seq uint32 + OSeqHi uint32 + SeqHi uint32 + ReplayWindow uint32 + Bmp []uint32 +} + +func (msg *XfrmReplayStateEsn) Serialize() []byte { + // We deliberately do not pass Bmp, as it gets set by the kernel. + return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/order.go b/vendor/github.com/vishvananda/netlink/order.go new file mode 100644 index 00000000..e28e153a --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/order.go @@ -0,0 +1,32 @@ +package netlink + +import ( + "encoding/binary" + + "github.com/vishvananda/netlink/nl" +) + +var ( + native = nl.NativeEndian() + networkOrder = binary.BigEndian +) + +func htonl(val uint32) []byte { + bytes := make([]byte, 4) + binary.BigEndian.PutUint32(bytes, val) + return bytes +} + +func htons(val uint16) []byte { + bytes := make([]byte, 2) + binary.BigEndian.PutUint16(bytes, val) + return bytes +} + +func ntohl(buf []byte) uint32 { + return binary.BigEndian.Uint32(buf) +} + +func ntohs(buf []byte) uint16 { + return binary.BigEndian.Uint16(buf) +} diff --git a/vendor/github.com/vishvananda/netlink/protinfo.go b/vendor/github.com/vishvananda/netlink/protinfo.go index f39ab8f4..ead3f2f1 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo.go +++ b/vendor/github.com/vishvananda/netlink/protinfo.go @@ -46,8 +46,5 @@ func boolToByte(x bool) []byte { } func byteToBool(x byte) bool { - if uint8(x) != 0 { - return true - } - return false + return uint8(x) != 0 } diff --git a/vendor/github.com/vishvananda/netlink/protinfo_linux.go b/vendor/github.com/vishvananda/netlink/protinfo_linux.go index 5b95d764..ea726953 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo_linux.go +++ b/vendor/github.com/vishvananda/netlink/protinfo_linux.go @@ -40,25 +40,31 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) { if err != nil { return pi, err } - var pi Protinfo - for _, info := range infos { - switch info.Attr.Type { - case nl.IFLA_BRPORT_MODE: - pi.Hairpin = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_GUARD: - pi.Guard = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_FAST_LEAVE: - pi.FastLeave = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_PROTECT: - pi.RootBlock = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_LEARNING: - pi.Learning = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_UNICAST_FLOOD: - pi.Flood = byteToBool(info.Value[0]) - } - } + pi = *parseProtinfo(infos) + return pi, nil } } return pi, fmt.Errorf("Device with index %d not found", base.Index) } + +func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo { + var pi Protinfo + for _, info := range infos { + switch info.Attr.Type { + case nl.IFLA_BRPORT_MODE: + pi.Hairpin = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_GUARD: + pi.Guard = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_FAST_LEAVE: + pi.FastLeave = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_PROTECT: + pi.RootBlock = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_LEARNING: + pi.Learning = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_UNICAST_FLOOD: + pi.Flood = byteToBool(info.Value[0]) + } + } + return &pi +} diff --git a/vendor/github.com/vishvananda/netlink/qdisc.go b/vendor/github.com/vishvananda/netlink/qdisc.go index 28f65f38..0ca86ebe 100644 --- a/vendor/github.com/vishvananda/netlink/qdisc.go +++ b/vendor/github.com/vishvananda/netlink/qdisc.go @@ -187,10 +187,11 @@ func (qdisc *Netem) Type() string { // Tbf is a classless qdisc that rate limits based on tokens type Tbf struct { QdiscAttrs - // TODO: handle 64bit rate properly - Rate uint64 - Limit uint32 - Buffer uint32 + Rate uint64 + Limit uint32 + Buffer uint32 + Peakrate uint64 + Minburst uint32 // TODO: handle other settings } diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go index 1bb48564..2c0deddb 100644 --- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go +++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go @@ -168,11 +168,20 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize()) } else if tbf, ok := qdisc.(*Tbf); ok { opt := nl.TcTbfQopt{} - // TODO: handle rate > uint32 opt.Rate.Rate = uint32(tbf.Rate) + opt.Peakrate.Rate = uint32(tbf.Peakrate) opt.Limit = tbf.Limit opt.Buffer = tbf.Buffer nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize()) + if tbf.Rate >= uint64(1<<32) { + nl.NewRtAttrChild(options, nl.TCA_TBF_RATE64, nl.Uint64Attr(tbf.Rate)) + } + if tbf.Peakrate >= uint64(1<<32) { + nl.NewRtAttrChild(options, nl.TCA_TBF_PRATE64, nl.Uint64Attr(tbf.Peakrate)) + } + if tbf.Peakrate > 0 { + nl.NewRtAttrChild(options, nl.TCA_TBF_PBURST, nl.Uint32Attr(tbf.Minburst)) + } } else if htb, ok := qdisc.(*Htb); ok { opt := nl.TcHtbGlob{} opt.Version = htb.Version @@ -418,10 +427,15 @@ func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { case nl.TCA_TBF_PARMS: opt := nl.DeserializeTcTbfQopt(datum.Value) tbf.Rate = uint64(opt.Rate.Rate) + tbf.Peakrate = uint64(opt.Peakrate.Rate) tbf.Limit = opt.Limit tbf.Buffer = opt.Buffer case nl.TCA_TBF_RATE64: - tbf.Rate = native.Uint64(datum.Value[0:4]) + tbf.Rate = native.Uint64(datum.Value[0:8]) + case nl.TCA_TBF_PRATE64: + tbf.Peakrate = native.Uint64(datum.Value[0:8]) + case nl.TCA_TBF_PBURST: + tbf.Minburst = native.Uint32(datum.Value[0:4]) } } return nil diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go index 61cf5ec5..03ac4b23 100644 --- a/vendor/github.com/vishvananda/netlink/route.go +++ b/vendor/github.com/vishvananda/netlink/route.go @@ -3,6 +3,7 @@ package netlink import ( "fmt" "net" + "strings" ) // Scope is an enum representing a route scope. @@ -10,6 +11,20 @@ type Scope uint8 type NextHopFlag int +type Destination interface { + Family() int + Decode([]byte) error + Encode() ([]byte, error) + String() string +} + +type Encap interface { + Type() int + Decode([]byte) error + Encode() ([]byte, error) + String() string +} + // Route represents a netlink route. type Route struct { LinkIndex int @@ -25,15 +40,36 @@ type Route struct { Type int Tos int Flags int + MPLSDst *int + NewDst Destination + Encap Encap } func (r Route) String() string { + elems := []string{} + if len(r.MultiPath) == 0 { + elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex)) + } + if r.MPLSDst != nil { + elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst)) + } else { + elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst)) + } + if r.NewDst != nil { + elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst)) + } + if r.Encap != nil { + elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap)) + } + elems = append(elems, fmt.Sprintf("Src: %s", r.Src)) if len(r.MultiPath) > 0 { - return fmt.Sprintf("{Dst: %s Src: %s Gw: %s Flags: %s Table: %d}", r.Dst, - r.Src, r.MultiPath, r.ListFlags(), r.Table) + elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath)) + } else { + elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw)) } - return fmt.Sprintf("{Ifindex: %d Dst: %s Src: %s Gw: %s Flags: %s Table: %d}", r.LinkIndex, r.Dst, - r.Src, r.Gw, r.ListFlags(), r.Table) + elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags())) + elems = append(elems, fmt.Sprintf("Table: %d", r.Table)) + return fmt.Sprintf("{%s}", strings.Join(elems, " ")) } func (r *Route) SetFlag(flag NextHopFlag) { @@ -59,8 +95,22 @@ type NexthopInfo struct { LinkIndex int Hops int Gw net.IP + Flags int + NewDst Destination + Encap Encap } func (n *NexthopInfo) String() string { - return fmt.Sprintf("{Ifindex: %d Weight: %d, Gw: %s}", n.LinkIndex, n.Hops+1, n.Gw) + elems := []string{} + elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex)) + if n.NewDst != nil { + elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst)) + } + if n.Encap != nil { + elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap)) + } + elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1)) + elems = append(elems, fmt.Sprintf("Gw: %d", n.Gw)) + elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags())) + return fmt.Sprintf("{%s}", strings.Join(elems, " ")) } diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go index b749ddb2..9e0f1f93 100644 --- a/vendor/github.com/vishvananda/netlink/route_linux.go +++ b/vendor/github.com/vishvananda/netlink/route_linux.go @@ -3,6 +3,7 @@ package netlink import ( "fmt" "net" + "strings" "syscall" "github.com/vishvananda/netlink/nl" @@ -42,16 +43,92 @@ var testFlags = []flagString{ {f: FLAG_PERVASIVE, s: "pervasive"}, } -func (r *Route) ListFlags() []string { +func listFlags(flag int) []string { var flags []string for _, tf := range testFlags { - if r.Flags&int(tf.f) != 0 { + if flag&int(tf.f) != 0 { flags = append(flags, tf.s) } } return flags } +func (r *Route) ListFlags() []string { + return listFlags(r.Flags) +} + +func (n *NexthopInfo) ListFlags() []string { + return listFlags(n.Flags) +} + +type MPLSDestination struct { + Labels []int +} + +func (d *MPLSDestination) Family() int { + return nl.FAMILY_MPLS +} + +func (d *MPLSDestination) Decode(buf []byte) error { + d.Labels = nl.DecodeMPLSStack(buf) + return nil +} + +func (d *MPLSDestination) Encode() ([]byte, error) { + return nl.EncodeMPLSStack(d.Labels...), nil +} + +func (d *MPLSDestination) String() string { + s := make([]string, 0, len(d.Labels)) + for _, l := range d.Labels { + s = append(s, fmt.Sprintf("%d", l)) + } + return strings.Join(s, "/") +} + +type MPLSEncap struct { + Labels []int +} + +func (e *MPLSEncap) Type() int { + return nl.LWTUNNEL_ENCAP_MPLS +} + +func (e *MPLSEncap) Decode(buf []byte) error { + if len(buf) < 4 { + return fmt.Errorf("Lack of bytes") + } + native := nl.NativeEndian() + l := native.Uint16(buf) + if len(buf) < int(l) { + return fmt.Errorf("Lack of bytes") + } + buf = buf[:l] + typ := native.Uint16(buf[2:]) + if typ != nl.MPLS_IPTUNNEL_DST { + return fmt.Errorf("Unknown MPLS Encap Type: %d", typ) + } + e.Labels = nl.DecodeMPLSStack(buf[4:]) + return nil +} + +func (e *MPLSEncap) Encode() ([]byte, error) { + s := nl.EncodeMPLSStack(e.Labels...) + native := nl.NativeEndian() + hdr := make([]byte, 4) + native.PutUint16(hdr, uint16(len(s)+4)) + native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST) + return append(hdr, s...), nil +} + +func (e *MPLSEncap) String() string { + s := make([]string, 0, len(e.Labels)) + for _, l := range e.Labels { + s = append(s, fmt.Sprintf("%d", l)) + } + return strings.Join(s, "/") +} + // RouteAdd will add a route to the system. // Equivalent to: `ip route add $route` func RouteAdd(route *Route) error { @@ -61,7 +138,22 @@ func RouteAdd(route *Route) error { // RouteAdd will add a route to the system. // Equivalent to: `ip route add $route` func (h *Handle) RouteAdd(route *Route) error { - req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) + flags := syscall.NLM_F_CREATE | syscall.NLM_F_EXCL | syscall.NLM_F_ACK + req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, flags) + return h.routeHandle(route, req, nl.NewRtMsg()) +} + +// RouteReplace will add a route to the system. +// Equivalent to: `ip route replace $route` +func RouteReplace(route *Route) error { + return pkgHandle.RouteReplace(route) +} + +// RouteReplace will add a route to the system. +// Equivalent to: `ip route replace $route` +func (h *Handle) RouteReplace(route *Route) error { + flags := syscall.NLM_F_CREATE | syscall.NLM_F_REPLACE | syscall.NLM_F_ACK + req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, flags) return h.routeHandle(route, req, nl.NewRtMsg()) } @@ -79,7 +171,7 @@ func (h *Handle) RouteDel(route *Route) error { } func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error { - if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil { + if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil { return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil") } @@ -98,6 +190,33 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg dstData = route.Dst.IP.To16() } rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData)) + } else if route.MPLSDst != nil { + family = nl.FAMILY_MPLS + msg.Dst_len = uint8(20) + msg.Type = syscall.RTN_UNICAST + rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst))) + } + + if route.NewDst != nil { + if family != -1 && family != route.NewDst.Family() { + return fmt.Errorf("new destination and destination are not the same address family") + } + buf, err := route.NewDst.Encode() + if err != nil { + return err + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_NEWDST, buf)) + } + + if route.Encap != nil { + buf := make([]byte, 2) + native.PutUint16(buf, uint16(route.Encap.Type())) + rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf)) + buf, err := route.Encap.Encode() + if err != nil { + return err + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP, buf)) } if route.Src != nil { @@ -138,26 +257,43 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg RtNexthop: syscall.RtNexthop{ Hops: uint8(nh.Hops), Ifindex: int32(nh.LinkIndex), - Len: uint16(syscall.SizeofRtNexthop), + Flags: uint8(nh.Flags), }, } - var gwData []byte + children := []nl.NetlinkRequestData{} if nh.Gw != nil { gwFamily := nl.GetIPFamily(nh.Gw) if family != -1 && family != gwFamily { return fmt.Errorf("gateway, source, and destination ip are not the same IP family") } - var gw *nl.RtAttr if gwFamily == FAMILY_V4 { - gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To4())) + children = append(children, nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To4()))) } else { - gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16())) + children = append(children, nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16()))) } - gwData = gw.Serialize() - rtnh.Len += uint16(len(gwData)) } + if nh.NewDst != nil { + if family != -1 && family != nh.NewDst.Family() { + return fmt.Errorf("new destination and destination are not the same address family") + } + buf, err := nh.NewDst.Encode() + if err != nil { + return err + } + children = append(children, nl.NewRtAttr(nl.RTA_NEWDST, buf)) + } + if nh.Encap != nil { + buf := make([]byte, 2) + native.PutUint16(buf, uint16(nh.Encap.Type())) + rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf)) + buf, err := nh.Encap.Encode() + if err != nil { + return err + } + children = append(children, nl.NewRtAttr(nl.RTA_ENCAP, buf)) + } + rtnh.Children = children buf = append(buf, rtnh.Serialize()...) - buf = append(buf, gwData...) } rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_MULTIPATH, buf)) } @@ -283,14 +419,22 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) continue case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src): continue - case filterMask&RT_FILTER_DST != 0 && filter.Dst != nil: - if route.Dst == nil { - continue - } - aMaskLen, aMaskBits := route.Dst.Mask.Size() - bMaskLen, bMaskBits := filter.Dst.Mask.Size() - if !(route.Dst.IP.Equal(filter.Dst.IP) && aMaskLen == bMaskLen && aMaskBits == bMaskBits) { - continue + case filterMask&RT_FILTER_DST != 0: + if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) { + if filter.Dst == nil { + if route.Dst != nil { + continue + } + } else { + if route.Dst == nil { + continue + } + aMaskLen, aMaskBits := route.Dst.Mask.Size() + bMaskLen, bMaskBits := filter.Dst.Mask.Size() + if !(route.Dst.IP.Equal(filter.Dst.IP) && aMaskLen == bMaskLen && aMaskBits == bMaskBits) { + continue + } + } } } } @@ -316,6 +460,7 @@ func deserializeRoute(m []byte) (Route, error) { } native := nl.NativeEndian() + var encap, encapType syscall.NetlinkRouteAttr for _, attr := range attrs { switch attr.Attr.Type { case syscall.RTA_GATEWAY: @@ -323,9 +468,17 @@ func deserializeRoute(m []byte) (Route, error) { case syscall.RTA_PREFSRC: route.Src = net.IP(attr.Value) case syscall.RTA_DST: - route.Dst = &net.IPNet{ - IP: attr.Value, - Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)), + if msg.Family == nl.FAMILY_MPLS { + stack := nl.DecodeMPLSStack(attr.Value) + if len(stack) == 0 || len(stack) > 1 { + return route, fmt.Errorf("invalid MPLS RTA_DST") + } + route.MPLSDst = &stack[0] + } else { + route.Dst = &net.IPNet{ + IP: attr.Value, + Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)), + } } case syscall.RTA_OIF: route.LinkIndex = int(native.Uint32(attr.Value[0:4])) @@ -347,17 +500,47 @@ func deserializeRoute(m []byte) (Route, error) { info := &NexthopInfo{ LinkIndex: int(nh.RtNexthop.Ifindex), Hops: int(nh.RtNexthop.Hops), + Flags: int(nh.RtNexthop.Flags), } attrs, err := nl.ParseRouteAttr(value[syscall.SizeofRtNexthop:int(nh.RtNexthop.Len)]) if err != nil { return nil, nil, err } + var encap, encapType syscall.NetlinkRouteAttr for _, attr := range attrs { switch attr.Attr.Type { case syscall.RTA_GATEWAY: info.Gw = net.IP(attr.Value) + case nl.RTA_NEWDST: + var d Destination + switch msg.Family { + case nl.FAMILY_MPLS: + d = &MPLSDestination{} + } + if err := d.Decode(attr.Value); err != nil { + return nil, nil, err + } + info.NewDst = d + case nl.RTA_ENCAP_TYPE: + encapType = attr + case nl.RTA_ENCAP: + encap = attr + } + } + + if len(encap.Value) != 0 && len(encapType.Value) != 0 { + typ := int(native.Uint16(encapType.Value[0:2])) + var e Encap + switch typ { + case nl.LWTUNNEL_ENCAP_MPLS: + e = &MPLSEncap{} + if err := e.Decode(encap.Value); err != nil { + return nil, nil, err + } } + info.Encap = e } + return info, value[int(nh.RtNexthop.Len):], nil } rest := attr.Value @@ -369,8 +552,36 @@ func deserializeRoute(m []byte) (Route, error) { route.MultiPath = append(route.MultiPath, info) rest = buf } + case nl.RTA_NEWDST: + var d Destination + switch msg.Family { + case nl.FAMILY_MPLS: + d = &MPLSDestination{} + } + if err := d.Decode(attr.Value); err != nil { + return route, err + } + route.NewDst = d + case nl.RTA_ENCAP_TYPE: + encapType = attr + case nl.RTA_ENCAP: + encap = attr + } + } + + if len(encap.Value) != 0 && len(encapType.Value) != 0 { + typ := int(native.Uint16(encapType.Value[0:2])) + var e Encap + switch typ { + case nl.LWTUNNEL_ENCAP_MPLS: + e = &MPLSEncap{} + if err := e.Decode(encap.Value); err != nil { + return route, err + } } + route.Encap = e } + return route, nil } diff --git a/vendor/github.com/vishvananda/netlink/route_unspecified.go b/vendor/github.com/vishvananda/netlink/route_unspecified.go index 1b205306..2701862b 100644 --- a/vendor/github.com/vishvananda/netlink/route_unspecified.go +++ b/vendor/github.com/vishvananda/netlink/route_unspecified.go @@ -5,3 +5,7 @@ package netlink func (r *Route) ListFlags() []string { return []string{} } + +func (n *NexthopInfo) ListFlags() []string { + return []string{} +} diff --git a/vendor/github.com/vishvananda/netlink/socket.go b/vendor/github.com/vishvananda/netlink/socket.go new file mode 100644 index 00000000..41aa7262 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/socket.go @@ -0,0 +1,27 @@ +package netlink + +import "net" + +// SocketID identifies a single socket. +type SocketID struct { + SourcePort uint16 + DestinationPort uint16 + Source net.IP + Destination net.IP + Interface uint32 + Cookie [2]uint32 +} + +// Socket represents a netlink socket. +type Socket struct { + Family uint8 + State uint8 + Timer uint8 + Retrans uint8 + ID SocketID + Expires uint32 + RQueue uint32 + WQueue uint32 + UID uint32 + INode uint32 +} diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go new file mode 100644 index 00000000..b42b84f0 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/socket_linux.go @@ -0,0 +1,159 @@ +package netlink + +import ( + "errors" + "fmt" + "net" + "syscall" + + "github.com/vishvananda/netlink/nl" +) + +const ( + sizeofSocketID = 0x30 + sizeofSocketRequest = sizeofSocketID + 0x8 + sizeofSocket = sizeofSocketID + 0x18 +) + +type socketRequest struct { + Family uint8 + Protocol uint8 + Ext uint8 + pad uint8 + States uint32 + ID SocketID +} + +type writeBuffer struct { + Bytes []byte + pos int +} + +func (b *writeBuffer) Write(c byte) { + b.Bytes[b.pos] = c + b.pos++ +} + +func (b *writeBuffer) Next(n int) []byte { + s := b.Bytes[b.pos : b.pos+n] + b.pos += n + return s +} + +func (r *socketRequest) Serialize() []byte { + b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)} + b.Write(r.Family) + b.Write(r.Protocol) + b.Write(r.Ext) + b.Write(r.pad) + native.PutUint32(b.Next(4), r.States) + networkOrder.PutUint16(b.Next(2), r.ID.SourcePort) + networkOrder.PutUint16(b.Next(2), r.ID.DestinationPort) + copy(b.Next(4), r.ID.Source.To4()) + b.Next(12) + copy(b.Next(4), r.ID.Destination.To4()) + b.Next(12) + native.PutUint32(b.Next(4), r.ID.Interface) + native.PutUint32(b.Next(4), r.ID.Cookie[0]) + native.PutUint32(b.Next(4), r.ID.Cookie[1]) + return b.Bytes +} + +func (r *socketRequest) Len() int { return sizeofSocketRequest } + +type readBuffer struct { + Bytes []byte + pos int +} + +func (b *readBuffer) Read() byte { + c := b.Bytes[b.pos] + b.pos++ + return c +} + +func (b *readBuffer) Next(n int) []byte { + s := b.Bytes[b.pos : b.pos+n] + b.pos += n + return s +} + +func (s *Socket) deserialize(b []byte) error { + if len(b) < sizeofSocket { + return fmt.Errorf("socket data short read (%d); want %d", len(b), sizeofSocket) + } + rb := readBuffer{Bytes: b} + s.Family = rb.Read() + s.State = rb.Read() + s.Timer = rb.Read() + s.Retrans = rb.Read() + s.ID.SourcePort = networkOrder.Uint16(rb.Next(2)) + s.ID.DestinationPort = networkOrder.Uint16(rb.Next(2)) + s.ID.Source = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) + rb.Next(12) + s.ID.Destination = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) + rb.Next(12) + s.ID.Interface = native.Uint32(rb.Next(4)) + s.ID.Cookie[0] = native.Uint32(rb.Next(4)) + s.ID.Cookie[1] = native.Uint32(rb.Next(4)) + s.Expires = native.Uint32(rb.Next(4)) + s.RQueue = native.Uint32(rb.Next(4)) + s.WQueue = native.Uint32(rb.Next(4)) + s.UID = native.Uint32(rb.Next(4)) + s.INode = native.Uint32(rb.Next(4)) + return nil +} + +// SocketGet returns the Socket identified by its local and remote addresses. +func SocketGet(local, remote net.Addr) (*Socket, error) { + localTCP, ok := local.(*net.TCPAddr) + if !ok { + return nil, ErrNotImplemented + } + remoteTCP, ok := remote.(*net.TCPAddr) + if !ok { + return nil, ErrNotImplemented + } + localIP := localTCP.IP.To4() + if localIP == nil { + return nil, ErrNotImplemented + } + remoteIP := remoteTCP.IP.To4() + if remoteIP == nil { + return nil, ErrNotImplemented + } + + s, err := nl.Subscribe(syscall.NETLINK_INET_DIAG) + if err != nil { + return nil, err + } + defer s.Close() + req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0) + req.AddData(&socketRequest{ + Family: syscall.AF_INET, + Protocol: syscall.IPPROTO_TCP, + ID: SocketID{ + SourcePort: uint16(localTCP.Port), + DestinationPort: uint16(remoteTCP.Port), + Source: localIP, + Destination: remoteIP, + Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE}, + }, + }) + s.Send(req) + msgs, err := s.Receive() + if err != nil { + return nil, err + } + if len(msgs) == 0 { + return nil, errors.New("no message nor error from netlink") + } + if len(msgs) > 2 { + return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs)) + } + sock := &Socket{} + if err := sock.deserialize(msgs[0].Data); err != nil { + return nil, err + } + return sock, nil +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go new file mode 100644 index 00000000..7b98c9cb --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go @@ -0,0 +1,98 @@ +package netlink + +import ( + "fmt" + "syscall" + + "github.com/vishvananda/netns" + + "github.com/vishvananda/netlink/nl" +) + +type XfrmMsg interface { + Type() nl.XfrmMsgType +} + +type XfrmMsgExpire struct { + XfrmState *XfrmState + Hard bool +} + +func (ue *XfrmMsgExpire) Type() nl.XfrmMsgType { + return nl.XFRM_MSG_EXPIRE +} + +func parseXfrmMsgExpire(b []byte) *XfrmMsgExpire { + var e XfrmMsgExpire + + msg := nl.DeserializeXfrmUserExpire(b) + e.XfrmState = xfrmStateFromXfrmUsersaInfo(&msg.XfrmUsersaInfo) + e.Hard = msg.Hard == 1 + + return &e +} + +func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error, + types ...nl.XfrmMsgType) error { + + groups, err := xfrmMcastGroups(types) + if err != nil { + return nil + } + s, err := nl.SubscribeAt(netns.None(), netns.None(), syscall.NETLINK_XFRM, groups...) + if err != nil { + return err + } + + if done != nil { + go func() { + <-done + s.Close() + }() + + } + + go func() { + defer close(ch) + for { + msgs, err := s.Receive() + if err != nil { + errorChan <- err + return + } + for _, m := range msgs { + switch m.Header.Type { + case nl.XFRM_MSG_EXPIRE: + ch <- parseXfrmMsgExpire(m.Data) + default: + errorChan <- fmt.Errorf("unsupported msg type: %x", m.Header.Type) + } + } + } + }() + + return nil +} + +func xfrmMcastGroups(types []nl.XfrmMsgType) ([]uint, error) { + groups := make([]uint, 0) + + if len(types) == 0 { + return nil, fmt.Errorf("no xfrm msg type specified") + } + + for _, t := range types { + var group uint + + switch t { + case nl.XFRM_MSG_EXPIRE: + group = nl.XFRMNLGRP_EXPIRE + default: + return nil, fmt.Errorf("unsupported group: %x", t) + } + + groups = append(groups, group) + } + + return groups, nil +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state.go b/vendor/github.com/vishvananda/netlink/xfrm_state.go index e25cde26..368a9b98 100644 --- a/vendor/github.com/vishvananda/netlink/xfrm_state.go +++ b/vendor/github.com/vishvananda/netlink/xfrm_state.go @@ -83,11 +83,12 @@ type XfrmState struct { Crypt *XfrmStateAlgo Aead *XfrmStateAlgo Encap *XfrmStateEncap + ESN bool } func (sa XfrmState) String() string { - return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Aead: %v,Encap: %v", - sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Aead, sa.Encap) + return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t", + sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN) } func (sa XfrmState) Print(stats bool) string { if !stats { diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go index 7b0b2e75..6a7bc0de 100644 --- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go +++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go @@ -60,6 +60,21 @@ func writeMark(m *XfrmMark) []byte { return mark.Serialize() } +func writeReplayEsn(replayWindow int) []byte { + replayEsn := &nl.XfrmReplayStateEsn{ + OSeq: 0, + Seq: 0, + OSeqHi: 0, + SeqHi: 0, + ReplayWindow: uint32(replayWindow), + } + + // taken from iproute2/ip/xfrm_state.c: + replayEsn.BmpLen = uint32((replayWindow + (4 * 8) - 1) / (4 * 8)) + + return replayEsn.Serialize() +} + // XfrmStateAdd will add an xfrm state to the system. // Equivalent to: `ip xfrm state add $state` func XfrmStateAdd(state *XfrmState) error { @@ -72,6 +87,12 @@ func (h *Handle) XfrmStateAdd(state *XfrmState) error { return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_NEWSA) } +// XfrmStateAllocSpi will allocate an xfrm state in the system. +// Equivalent to: `ip xfrm state allocspi` +func XfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { + return pkgHandle.xfrmStateAllocSpi(state) +} + // XfrmStateUpdate will update an xfrm state to the system. // Equivalent to: `ip xfrm state update $state` func XfrmStateUpdate(state *XfrmState) error { @@ -85,21 +106,23 @@ func (h *Handle) XfrmStateUpdate(state *XfrmState) error { } func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error { + // A state with spi 0 can't be deleted so don't allow it to be set if state.Spi == 0 { return fmt.Errorf("Spi must be set when adding xfrm state.") } req := h.newNetlinkRequest(nlProto, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) - msg := &nl.XfrmUsersaInfo{} - msg.Family = uint16(nl.GetIPFamily(state.Dst)) - msg.Id.Daddr.FromIP(state.Dst) - msg.Saddr.FromIP(state.Src) - msg.Id.Proto = uint8(state.Proto) - msg.Mode = uint8(state.Mode) - msg.Id.Spi = nl.Swap32(uint32(state.Spi)) - msg.Reqid = uint32(state.Reqid) - msg.ReplayWindow = uint8(state.ReplayWindow) + msg := xfrmUsersaInfoFromXfrmState(state) + + if state.ESN { + if state.ReplayWindow == 0 { + return fmt.Errorf("ESN flag set without ReplayWindow") + } + msg.Flags |= nl.XFRM_STATE_ESN + msg.ReplayWindow = 0 + } + limitsToLft(state.Limits, &msg.Lft) req.AddData(msg) @@ -129,11 +152,44 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error { out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) req.AddData(out) } + if state.ESN { + out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow)) + req.AddData(out) + } _, err := req.Execute(syscall.NETLINK_XFRM, 0) return err } +func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { + req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI, + syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) + + msg := &nl.XfrmUserSpiInfo{} + msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state)) + // 1-255 is reserved by IANA for future use + msg.Min = 0x100 + msg.Max = 0xffffffff + req.AddData(msg) + + if state.Mark != nil { + out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) + req.AddData(out) + } + + msgs, err := req.Execute(syscall.NETLINK_XFRM, 0) + if err != nil { + return nil, err + } + + s, err := parseXfrmState(msgs[0], FAMILY_ALL) + if err != nil { + return nil, err + } + + return s, err +} + // XfrmStateDel will delete an xfrm state from the system. Note that // the Algos are ignored when matching the state to delete. // Equivalent to: `ip xfrm state del $state` @@ -241,14 +297,7 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState var familyError = fmt.Errorf("family error") -func parseXfrmState(m []byte, family int) (*XfrmState, error) { - msg := nl.DeserializeXfrmUsersaInfo(m) - - // This is mainly for the state dump - if family != FAMILY_ALL && family != int(msg.Family) { - return nil, familyError - } - +func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState { var state XfrmState state.Dst = msg.Id.Daddr.ToIP() @@ -260,6 +309,19 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) { state.ReplayWindow = int(msg.ReplayWindow) lftToLimits(&msg.Lft, &state.Limits) + return &state +} + +func parseXfrmState(m []byte, family int) (*XfrmState, error) { + msg := nl.DeserializeXfrmUsersaInfo(m) + + // This is mainly for the state dump + if family != FAMILY_ALL && family != int(msg.Family) { + return nil, familyError + } + + state := xfrmStateFromXfrmUsersaInfo(msg) + attrs, err := nl.ParseRouteAttr(m[nl.SizeofXfrmUsersaInfo:]) if err != nil { return nil, err @@ -310,7 +372,7 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) { } } - return &state, nil + return state, nil } // XfrmStateFlush will flush the xfrm state on the system. @@ -366,3 +428,17 @@ func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) { func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) { *lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft)) } + +func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo { + msg := &nl.XfrmUsersaInfo{} + msg.Family = uint16(nl.GetIPFamily(state.Dst)) + msg.Id.Daddr.FromIP(state.Dst) + msg.Saddr.FromIP(state.Src) + msg.Id.Proto = uint8(state.Proto) + msg.Mode = uint8(state.Mode) + msg.Id.Spi = nl.Swap32(uint32(state.Spi)) + msg.Reqid = uint32(state.Reqid) + msg.ReplayWindow = uint8(state.ReplayWindow) + + return msg +} diff --git a/vendor/golang.org/x/sys/AUTHORS b/vendor/golang.org/x/sys/AUTHORS new file mode 100644 index 00000000..15167cd7 --- /dev/null +++ b/vendor/golang.org/x/sys/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/sys/CONTRIBUTORS b/vendor/golang.org/x/sys/CONTRIBUTORS new file mode 100644 index 00000000..1c4577e9 --- /dev/null +++ b/vendor/golang.org/x/sys/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksyscall.pl b/vendor/golang.org/x/sys/unix/mksyscall.pl old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksyscall_solaris.pl b/vendor/golang.org/x/sys/unix/mksyscall_solaris.pl old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl b/vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksysnum_darwin.pl b/vendor/golang.org/x/sys/unix/mksysnum_darwin.pl old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl b/vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl b/vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksysnum_linux.pl b/vendor/golang.org/x/sys/unix/mksysnum_linux.pl old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl b/vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl old mode 100644 new mode 100755 diff --git a/vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl b/vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl old mode 100644 new mode 100755