aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2018-09-25 12:41:40 -0400
committerMatthew Heon <matthew.heon@gmail.com>2018-10-04 17:34:59 -0400
commitbc5fac3a7cbef9c73dd3a739c830066c88fa595f (patch)
tree2ea9abb89ae7a6c502bc0734aab9345320a2d285
parente4ded6ce7fa7db246d7e13d17abdbadeb7ec8cfe (diff)
downloadpodman-bc5fac3a7cbef9c73dd3a739c830066c88fa595f.tar.gz
podman-bc5fac3a7cbef9c73dd3a739c830066c88fa595f.tar.bz2
podman-bc5fac3a7cbef9c73dd3a739c830066c88fa595f.zip
Update libnetwork vendor to current master to fix CI
Avoid a Sirupsen vs sirupsen class for logrus by updating to master. Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/docker/libnetwork/README.md15
-rw-r--r--vendor/github.com/docker/libnetwork/ipamutils/utils.go135
-rw-r--r--vendor/github.com/docker/libnetwork/netutils/utils.go11
-rw-r--r--vendor/github.com/docker/libnetwork/netutils/utils_freebsd.go23
-rw-r--r--vendor/github.com/docker/libnetwork/netutils/utils_linux.go84
-rw-r--r--vendor/github.com/docker/libnetwork/netutils/utils_windows.go25
-rw-r--r--vendor/github.com/docker/libnetwork/ns/init_linux.go140
-rw-r--r--vendor/github.com/docker/libnetwork/ns/init_windows.go3
-rw-r--r--vendor/github.com/docker/libnetwork/osl/interface_freebsd.go4
-rw-r--r--vendor/github.com/docker/libnetwork/osl/interface_linux.go460
-rw-r--r--vendor/github.com/docker/libnetwork/osl/interface_windows.go4
-rw-r--r--vendor/github.com/docker/libnetwork/osl/kernel/knobs.go16
-rw-r--r--vendor/github.com/docker/libnetwork/osl/kernel/knobs_linux.go47
-rw-r--r--vendor/github.com/docker/libnetwork/osl/kernel/knobs_unsupported.go7
-rw-r--r--vendor/github.com/docker/libnetwork/osl/namespace_linux.go657
-rw-r--r--vendor/github.com/docker/libnetwork/osl/namespace_unsupported.go17
-rw-r--r--vendor/github.com/docker/libnetwork/osl/namespace_windows.go38
-rw-r--r--vendor/github.com/docker/libnetwork/osl/neigh_freebsd.go4
-rw-r--r--vendor/github.com/docker/libnetwork/osl/neigh_linux.go194
-rw-r--r--vendor/github.com/docker/libnetwork/osl/neigh_windows.go4
-rw-r--r--vendor/github.com/docker/libnetwork/osl/options_linux.go73
-rw-r--r--vendor/github.com/docker/libnetwork/osl/route_linux.go203
-rw-r--r--vendor/github.com/docker/libnetwork/osl/sandbox.go187
-rw-r--r--vendor/github.com/docker/libnetwork/osl/sandbox_freebsd.go44
-rw-r--r--vendor/github.com/docker/libnetwork/osl/sandbox_unsupported.go22
-rw-r--r--vendor/github.com/docker/libnetwork/resolvconf/dns/resolvconf.go11
-rw-r--r--vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go44
-rw-r--r--vendor/github.com/docker/libnetwork/types/types.go78
-rw-r--r--vendor/github.com/docker/libnetwork/vendor.conf50
30 files changed, 2548 insertions, 54 deletions
diff --git a/vendor.conf b/vendor.conf
index 48f127773..d613dceb2 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -97,4 +97,4 @@ github.com/openshift/imagebuilder master
github.com/ulikunitz/xz v0.5.4
github.com/mailru/easyjson 03f2033d19d5860aef995fe360ac7d395cd8ce65
github.com/coreos/go-iptables 25d087f3cffd9aedc0c2b7eff25f23cbf3c20fe1
-github.com/docker/libnetwork v0.7.2-rc.1 \ No newline at end of file
+github.com/docker/libnetwork 20461b8539336a4b5fcf551a86dd24ebae211984
diff --git a/vendor/github.com/docker/libnetwork/README.md b/vendor/github.com/docker/libnetwork/README.md
index 3f10a0311..a9020381a 100644
--- a/vendor/github.com/docker/libnetwork/README.md
+++ b/vendor/github.com/docker/libnetwork/README.md
@@ -1,6 +1,6 @@
# libnetwork - networking for containers
-[![Circle CI](https://circleci.com/gh/docker/libnetwork/tree/master.svg?style=svg)](https://circleci.com/gh/docker/libnetwork/tree/master) [![Coverage Status](https://coveralls.io/repos/docker/libnetwork/badge.svg)](https://coveralls.io/r/docker/libnetwork) [![GoDoc](https://godoc.org/github.com/docker/libnetwork?status.svg)](https://godoc.org/github.com/docker/libnetwork)
+[![Circle CI](https://circleci.com/gh/docker/libnetwork/tree/master.svg?style=svg)](https://circleci.com/gh/docker/libnetwork/tree/master) [![Coverage Status](https://coveralls.io/repos/docker/libnetwork/badge.svg)](https://coveralls.io/r/docker/libnetwork) [![GoDoc](https://godoc.org/github.com/docker/libnetwork?status.svg)](https://godoc.org/github.com/docker/libnetwork) [![Go Report Card](https://goreportcard.com/badge/github.com/docker/libnetwork)](https://goreportcard.com/report/github.com/docker/libnetwork)
Libnetwork provides a native Go implementation for connecting containers
@@ -15,6 +15,17 @@ There are many networking solutions available to suit a broad range of use-cases
```go
+import (
+ "fmt"
+ "log"
+
+ "github.com/docker/docker/pkg/reexec"
+ "github.com/docker/libnetwork"
+ "github.com/docker/libnetwork/config"
+ "github.com/docker/libnetwork/netlabel"
+ "github.com/docker/libnetwork/options"
+)
+
func main() {
if reexec.Init() {
return
@@ -34,7 +45,7 @@ func main() {
// Create a network for containers to join.
// NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can use.
- network, err := controller.NewNetwork(networkType, "network1")
+ network, err := controller.NewNetwork(networkType, "network1", "")
if err != nil {
log.Fatalf("controller.NewNetwork: %s", err)
}
diff --git a/vendor/github.com/docker/libnetwork/ipamutils/utils.go b/vendor/github.com/docker/libnetwork/ipamutils/utils.go
new file mode 100644
index 000000000..3fd37cd88
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/ipamutils/utils.go
@@ -0,0 +1,135 @@
+// Package ipamutils provides utility functions for ipam management
+package ipamutils
+
+import (
+ "fmt"
+ "net"
+ "sync"
+)
+
+var (
+ // PredefinedLocalScopeDefaultNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
+ // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGlobalScopeDefaultNetworks`
+ PredefinedLocalScopeDefaultNetworks []*net.IPNet
+ // PredefinedGlobalScopeDefaultNetworks contains a list of 64K IPv4 private networks with host size 8
+ // (10.x.x.x/24) which do not overlap with the networks in `PredefinedLocalScopeDefaultNetworks`
+ PredefinedGlobalScopeDefaultNetworks []*net.IPNet
+ mutex sync.Mutex
+ localScopeDefaultNetworks = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
+ {"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16},
+ {"192.168.0.0/16", 20}}
+ globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}}
+)
+
+// NetworkToSplit represent a network that has to be split in chunks with mask length Size.
+// Each subnet in the set is derived from the Base pool. Base is to be passed
+// in CIDR format.
+// Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256
+// 10.10.[0-255].0/24 address pools
+type NetworkToSplit struct {
+ Base string `json:"base"`
+ Size int `json:"size"`
+}
+
+func init() {
+ var err error
+ if PredefinedGlobalScopeDefaultNetworks, err = splitNetworks(globalScopeDefaultNetworks); err != nil {
+ //we are going to panic in case of error as we should never get into this state
+ panic("InitAddressPools failed to initialize the global scope default address pool")
+ }
+
+ if PredefinedLocalScopeDefaultNetworks, err = splitNetworks(localScopeDefaultNetworks); err != nil {
+ //we are going to panic in case of error as we should never get into this state
+ panic("InitAddressPools failed to initialize the local scope default address pool")
+ }
+}
+
+// configDefaultNetworks configures local as well global default pool based on input
+func configDefaultNetworks(defaultAddressPool []*NetworkToSplit, result *[]*net.IPNet) error {
+ mutex.Lock()
+ defer mutex.Unlock()
+ defaultNetworks, err := splitNetworks(defaultAddressPool)
+ if err != nil {
+ return err
+ }
+ *result = defaultNetworks
+ return nil
+}
+
+// GetGlobalScopeDefaultNetworks returns PredefinedGlobalScopeDefaultNetworks
+func GetGlobalScopeDefaultNetworks() []*net.IPNet {
+ mutex.Lock()
+ defer mutex.Unlock()
+ return PredefinedGlobalScopeDefaultNetworks
+}
+
+// GetLocalScopeDefaultNetworks returns PredefinedLocalScopeDefaultNetworks
+func GetLocalScopeDefaultNetworks() []*net.IPNet {
+ mutex.Lock()
+ defer mutex.Unlock()
+ return PredefinedLocalScopeDefaultNetworks
+}
+
+// ConfigGlobalScopeDefaultNetworks configures global default pool.
+// Ideally this will be called from SwarmKit as part of swarm init
+func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
+ if defaultAddressPool == nil {
+ defaultAddressPool = globalScopeDefaultNetworks
+ }
+ return configDefaultNetworks(defaultAddressPool, &PredefinedGlobalScopeDefaultNetworks)
+}
+
+// ConfigLocalScopeDefaultNetworks configures local default pool.
+// Ideally this will be called during libnetwork init
+func ConfigLocalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
+ if defaultAddressPool == nil {
+ return nil
+ }
+ return configDefaultNetworks(defaultAddressPool, &PredefinedLocalScopeDefaultNetworks)
+}
+
+// splitNetworks takes a slice of networks, split them accordingly and returns them
+func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) {
+ localPools := make([]*net.IPNet, 0, len(list))
+
+ for _, p := range list {
+ _, b, err := net.ParseCIDR(p.Base)
+ if err != nil {
+ return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err)
+ }
+ ones, _ := b.Mask.Size()
+ if p.Size <= 0 || p.Size < ones {
+ return nil, fmt.Errorf("invalid pools size: %d", p.Size)
+ }
+ localPools = append(localPools, splitNetwork(p.Size, b)...)
+ }
+ return localPools, nil
+}
+
+func splitNetwork(size int, base *net.IPNet) []*net.IPNet {
+ one, bits := base.Mask.Size()
+ mask := net.CIDRMask(size, bits)
+ n := 1 << uint(size-one)
+ s := uint(bits - size)
+ list := make([]*net.IPNet, 0, n)
+
+ for i := 0; i < n; i++ {
+ ip := copyIP(base.IP)
+ addIntToIP(ip, uint(i<<s))
+ list = append(list, &net.IPNet{IP: ip, Mask: mask})
+ }
+ return list
+}
+
+func copyIP(from net.IP) net.IP {
+ ip := make([]byte, len(from))
+ copy(ip, from)
+ return ip
+}
+
+func addIntToIP(array net.IP, ordinal uint) {
+ for i := len(array) - 1; i >= 0; i-- {
+ array[i] |= (byte)(ordinal & 0xff)
+ ordinal >>= 8
+ }
+}
diff --git a/vendor/github.com/docker/libnetwork/netutils/utils.go b/vendor/github.com/docker/libnetwork/netutils/utils.go
index 482e4f038..7de98f6b0 100644
--- a/vendor/github.com/docker/libnetwork/netutils/utils.go
+++ b/vendor/github.com/docker/libnetwork/netutils/utils.go
@@ -14,13 +14,6 @@ import (
"github.com/docker/libnetwork/types"
)
-// constants for the IP address type
-const (
- IP = iota // IPv4 and IPv6
- IPv4
- IPv6
-)
-
var (
// ErrNetworkOverlapsWithNameservers preformatted error
ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
@@ -177,10 +170,10 @@ func ReverseIP(IP string) string {
return strings.Join(reverseIP, ".")
}
-// ParseAlias parses and validates the specified string as a alias format (name:alias)
+// ParseAlias parses and validates the specified string as an alias format (name:alias)
func ParseAlias(val string) (string, string, error) {
if val == "" {
- return "", "", fmt.Errorf("empty string specified for alias")
+ return "", "", errors.New("empty string specified for alias")
}
arr := strings.Split(val, ":")
if len(arr) > 2 {
diff --git a/vendor/github.com/docker/libnetwork/netutils/utils_freebsd.go b/vendor/github.com/docker/libnetwork/netutils/utils_freebsd.go
new file mode 100644
index 000000000..02bcd32aa
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/netutils/utils_freebsd.go
@@ -0,0 +1,23 @@
+package netutils
+
+import (
+ "net"
+
+ "github.com/docker/libnetwork/types"
+)
+
+// ElectInterfaceAddresses looks for an interface on the OS with the specified name
+// and returns returns all its IPv4 and IPv6 addresses in CIDR notation.
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned.
+// If the interface does not exist, it chooses from a predefined
+// list the first IPv4 address which does not conflict with other
+// interfaces on the system.
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
+ return nil, nil, types.NotImplementedErrorf("not supported on freebsd")
+}
+
+// FindAvailableNetwork returns a network from the passed list which does not
+// overlap with existing interfaces in the system
+func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
+ return nil, types.NotImplementedErrorf("not supported on freebsd")
+}
diff --git a/vendor/github.com/docker/libnetwork/netutils/utils_linux.go b/vendor/github.com/docker/libnetwork/netutils/utils_linux.go
index 782e542a5..10a5e109e 100644
--- a/vendor/github.com/docker/libnetwork/netutils/utils_linux.go
+++ b/vendor/github.com/docker/libnetwork/netutils/utils_linux.go
@@ -4,24 +4,31 @@
package netutils
import (
+ "fmt"
"net"
"strings"
+ "github.com/docker/libnetwork/ipamutils"
+ "github.com/docker/libnetwork/ns"
+ "github.com/docker/libnetwork/osl"
+ "github.com/docker/libnetwork/resolvconf"
"github.com/docker/libnetwork/types"
"github.com/vishvananda/netlink"
)
var (
- networkGetRoutesFct = netlink.RouteList
+ networkGetRoutesFct func(netlink.Link, int) ([]netlink.Route, error)
)
// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
func CheckRouteOverlaps(toCheck *net.IPNet) error {
+ if networkGetRoutesFct == nil {
+ networkGetRoutesFct = ns.NlHandle().RouteList
+ }
networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
if err != nil {
return err
}
-
for _, network := range networks {
if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
return ErrNetworkOverlaps
@@ -33,13 +40,18 @@ func CheckRouteOverlaps(toCheck *net.IPNet) error {
// GenerateIfaceName returns an interface name using the passed in
// prefix and the length of random bytes. The api ensures that the
// there are is no interface which exists with that name.
-func GenerateIfaceName(prefix string, len int) (string, error) {
+func GenerateIfaceName(nlh *netlink.Handle, prefix string, len int) (string, error) {
+ linkByName := netlink.LinkByName
+ if nlh != nil {
+ linkByName = nlh.LinkByName
+ }
for i := 0; i < 3; i++ {
name, err := GenerateRandomName(prefix, len)
if err != nil {
continue
}
- if _, err := netlink.LinkByName(name); err != nil {
+ _, err = linkByName(name)
+ if err != nil {
if strings.Contains(err.Error(), "not found") {
return name, nil
}
@@ -48,3 +60,67 @@ func GenerateIfaceName(prefix string, len int) (string, error) {
}
return "", types.InternalErrorf("could not generate interface name")
}
+
+// ElectInterfaceAddresses looks for an interface on the OS with the
+// specified name and returns returns all its IPv4 and IPv6 addresses in CIDR notation.
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned.
+// If the interface does not exist, it chooses from a predefined
+// list the first IPv4 address which does not conflict with other
+// interfaces on the system.
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
+ var (
+ v4Nets []*net.IPNet
+ v6Nets []*net.IPNet
+ )
+
+ defer osl.InitOSContext()()
+
+ link, _ := ns.NlHandle().LinkByName(name)
+ if link != nil {
+ v4addr, err := ns.NlHandle().AddrList(link, netlink.FAMILY_V4)
+ if err != nil {
+ return nil, nil, err
+ }
+ v6addr, err := ns.NlHandle().AddrList(link, netlink.FAMILY_V6)
+ if err != nil {
+ return nil, nil, err
+ }
+ for _, nlAddr := range v4addr {
+ v4Nets = append(v4Nets, nlAddr.IPNet)
+ }
+ for _, nlAddr := range v6addr {
+ v6Nets = append(v6Nets, nlAddr.IPNet)
+ }
+ }
+
+ if link == nil || len(v4Nets) == 0 {
+ // Choose from predefined local scope networks
+ v4Net, err := FindAvailableNetwork(ipamutils.PredefinedLocalScopeDefaultNetworks)
+ if err != nil {
+ return nil, nil, err
+ }
+ v4Nets = append(v4Nets, v4Net)
+ }
+
+ return v4Nets, v6Nets, nil
+}
+
+// FindAvailableNetwork returns a network from the passed list which does not
+// overlap with existing interfaces in the system
+func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
+ // We don't check for an error here, because we don't really care if we
+ // can't read /etc/resolv.conf. So instead we skip the append if resolvConf
+ // is nil. It either doesn't exist, or we can't read it for some reason.
+ var nameservers []string
+ if rc, err := resolvconf.Get(); err == nil {
+ nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
+ }
+ for _, nw := range list {
+ if err := CheckNameserverOverlaps(nameservers, nw); err == nil {
+ if err := CheckRouteOverlaps(nw); err == nil {
+ return nw, nil
+ }
+ }
+ }
+ return nil, fmt.Errorf("no available network")
+}
diff --git a/vendor/github.com/docker/libnetwork/netutils/utils_windows.go b/vendor/github.com/docker/libnetwork/netutils/utils_windows.go
new file mode 100644
index 000000000..73af44ec7
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/netutils/utils_windows.go
@@ -0,0 +1,25 @@
+package netutils
+
+import (
+ "net"
+
+ "github.com/docker/libnetwork/types"
+)
+
+// ElectInterfaceAddresses looks for an interface on the OS with the specified name
+// and returns returns all its IPv4 and IPv6 addresses in CIDR notation.
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned.
+// If the interface does not exist, it chooses from a predefined
+// list the first IPv4 address which does not conflict with other
+// interfaces on the system.
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
+ return nil, nil, types.NotImplementedErrorf("not supported on windows")
+}
+
+// FindAvailableNetwork returns a network from the passed list which does not
+// overlap with existing interfaces in the system
+
+// TODO : Use appropriate windows APIs to identify non-overlapping subnets
+func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
+ return nil, nil
+}
diff --git a/vendor/github.com/docker/libnetwork/ns/init_linux.go b/vendor/github.com/docker/libnetwork/ns/init_linux.go
new file mode 100644
index 000000000..567a6242a
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/ns/init_linux.go
@@ -0,0 +1,140 @@
+package ns
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/sirupsen/logrus"
+ "github.com/vishvananda/netlink"
+ "github.com/vishvananda/netns"
+)
+
+var (
+ initNs netns.NsHandle
+ initNl *netlink.Handle
+ initOnce sync.Once
+ // NetlinkSocketsTimeout represents the default timeout duration for the sockets
+ NetlinkSocketsTimeout = 3 * time.Second
+)
+
+// Init initializes a new network namespace
+func Init() {
+ var err error
+ initNs, err = netns.Get()
+ if err != nil {
+ logrus.Errorf("could not get initial namespace: %v", err)
+ }
+ initNl, err = netlink.NewHandle(getSupportedNlFamilies()...)
+ if err != nil {
+ logrus.Errorf("could not create netlink handle on initial namespace: %v", err)
+ }
+ err = initNl.SetSocketTimeout(NetlinkSocketsTimeout)
+ if err != nil {
+ logrus.Warnf("Failed to set the timeout on the default netlink handle sockets: %v", err)
+ }
+}
+
+// SetNamespace sets the initial namespace handler
+func SetNamespace() error {
+ initOnce.Do(Init)
+ if err := netns.Set(initNs); err != nil {
+ linkInfo, linkErr := getLink()
+ if linkErr != nil {
+ linkInfo = linkErr.Error()
+ }
+ return fmt.Errorf("failed to set to initial namespace, %v, initns fd %d: %v", linkInfo, initNs, err)
+ }
+ return nil
+}
+
+// ParseHandlerInt transforms the namespace handler into an integer
+func ParseHandlerInt() int {
+ return int(getHandler())
+}
+
+// GetHandler returns the namespace handler
+func getHandler() netns.NsHandle {
+ initOnce.Do(Init)
+ return initNs
+}
+
+func getLink() (string, error) {
+ return os.Readlink(fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid()))
+}
+
+// NlHandle returns the netlink handler
+func NlHandle() *netlink.Handle {
+ initOnce.Do(Init)
+ return initNl
+}
+
+func getSupportedNlFamilies() []int {
+ fams := []int{syscall.NETLINK_ROUTE}
+ // NETLINK_XFRM test
+ if err := loadXfrmModules(); err != nil {
+ if checkXfrmSocket() != nil {
+ logrus.Warnf("Could not load necessary modules for IPSEC rules: %v", err)
+ } else {
+ fams = append(fams, syscall.NETLINK_XFRM)
+ }
+ } else {
+ fams = append(fams, syscall.NETLINK_XFRM)
+ }
+ // NETLINK_NETFILTER test
+ if err := loadNfConntrackModules(); err != nil {
+ if checkNfSocket() != nil {
+ logrus.Warnf("Could not load necessary modules for Conntrack: %v", err)
+ } else {
+ fams = append(fams, syscall.NETLINK_NETFILTER)
+ }
+ } else {
+ fams = append(fams, syscall.NETLINK_NETFILTER)
+ }
+
+ return fams
+}
+
+func loadXfrmModules() error {
+ if out, err := exec.Command("modprobe", "-va", "xfrm_user").CombinedOutput(); err != nil {
+ return fmt.Errorf("Running modprobe xfrm_user failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
+ }
+ if out, err := exec.Command("modprobe", "-va", "xfrm_algo").CombinedOutput(); err != nil {
+ return fmt.Errorf("Running modprobe xfrm_algo failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
+ }
+ return nil
+}
+
+// API check on required xfrm modules (xfrm_user, xfrm_algo)
+func checkXfrmSocket() error {
+ fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_XFRM)
+ if err != nil {
+ return err
+ }
+ syscall.Close(fd)
+ return nil
+}
+
+func loadNfConntrackModules() error {
+ if out, err := exec.Command("modprobe", "-va", "nf_conntrack").CombinedOutput(); err != nil {
+ return fmt.Errorf("Running modprobe nf_conntrack failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
+ }
+ if out, err := exec.Command("modprobe", "-va", "nf_conntrack_netlink").CombinedOutput(); err != nil {
+ return fmt.Errorf("Running modprobe nf_conntrack_netlink failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
+ }
+ return nil
+}
+
+// API check on required nf_conntrack* modules (nf_conntrack, nf_conntrack_netlink)
+func checkNfSocket() error {
+ fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_NETFILTER)
+ if err != nil {
+ return err
+ }
+ syscall.Close(fd)
+ return nil
+}
diff --git a/vendor/github.com/docker/libnetwork/ns/init_windows.go b/vendor/github.com/docker/libnetwork/ns/init_windows.go
new file mode 100644
index 000000000..f5838f81d
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/ns/init_windows.go
@@ -0,0 +1,3 @@
+package ns
+
+// File is present so that go build ./... is closer to working on Windows from repo root.
diff --git a/vendor/github.com/docker/libnetwork/osl/interface_freebsd.go b/vendor/github.com/docker/libnetwork/osl/interface_freebsd.go
new file mode 100644
index 000000000..9c0141fd9
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/interface_freebsd.go
@@ -0,0 +1,4 @@
+package osl
+
+// IfaceOption is a function option type to set interface options
+type IfaceOption func()
diff --git a/vendor/github.com/docker/libnetwork/osl/interface_linux.go b/vendor/github.com/docker/libnetwork/osl/interface_linux.go
new file mode 100644
index 000000000..4f8ff3d63
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/interface_linux.go
@@ -0,0 +1,460 @@
+package osl
+
+import (
+ "fmt"
+ "net"
+ "regexp"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/docker/libnetwork/ns"
+ "github.com/docker/libnetwork/types"
+ "github.com/sirupsen/logrus"
+ "github.com/vishvananda/netlink"
+ "github.com/vishvananda/netns"
+)
+
+// IfaceOption is a function option type to set interface options
+type IfaceOption func(i *nwIface)
+
+type nwIface struct {
+ srcName string
+ dstName string
+ master string
+ dstMaster string
+ mac net.HardwareAddr
+ address *net.IPNet
+ addressIPv6 *net.IPNet
+ llAddrs []*net.IPNet
+ routes []*net.IPNet
+ bridge bool
+ ns *networkNamespace
+ sync.Mutex
+}
+
+func (i *nwIface) SrcName() string {
+ i.Lock()
+ defer i.Unlock()
+
+ return i.srcName
+}
+
+func (i *nwIface) DstName() string {
+ i.Lock()
+ defer i.Unlock()
+
+ return i.dstName
+}
+
+func (i *nwIface) DstMaster() string {
+ i.Lock()
+ defer i.Unlock()
+
+ return i.dstMaster
+}
+
+func (i *nwIface) Bridge() bool {
+ i.Lock()
+ defer i.Unlock()
+
+ return i.bridge
+}
+
+func (i *nwIface) Master() string {
+ i.Lock()
+ defer i.Unlock()
+
+ return i.master
+}
+
+func (i *nwIface) MacAddress() net.HardwareAddr {
+ i.Lock()
+ defer i.Unlock()
+
+ return types.GetMacCopy(i.mac)
+}
+
+func (i *nwIface) Address() *net.IPNet {
+ i.Lock()
+ defer i.Unlock()
+
+ return types.GetIPNetCopy(i.address)
+}
+
+func (i *nwIface) AddressIPv6() *net.IPNet {
+ i.Lock()
+ defer i.Unlock()
+
+ return types.GetIPNetCopy(i.addressIPv6)
+}
+
+func (i *nwIface) LinkLocalAddresses() []*net.IPNet {
+ i.Lock()
+ defer i.Unlock()
+
+ return i.llAddrs
+}
+
+func (i *nwIface) Routes() []*net.IPNet {
+ i.Lock()
+ defer i.Unlock()
+
+ routes := make([]*net.IPNet, len(i.routes))
+ for index, route := range i.routes {
+ r := types.GetIPNetCopy(route)
+ routes[index] = r
+ }
+
+ return routes
+}
+
+func (n *networkNamespace) Interfaces() []Interface {
+ n.Lock()
+ defer n.Unlock()
+
+ ifaces := make([]Interface, len(n.iFaces))
+
+ for i, iface := range n.iFaces {
+ ifaces[i] = iface
+ }
+
+ return ifaces
+}
+
+func (i *nwIface) Remove() error {
+ i.Lock()
+ n := i.ns
+ i.Unlock()
+
+ n.Lock()
+ isDefault := n.isDefault
+ nlh := n.nlHandle
+ n.Unlock()
+
+ // Find the network interface identified by the DstName attribute.
+ iface, err := nlh.LinkByName(i.DstName())
+ if err != nil {
+ return err
+ }
+
+ // Down the interface before configuring
+ if err := nlh.LinkSetDown(iface); err != nil {
+ return err
+ }
+
+ err = nlh.LinkSetName(iface, i.SrcName())
+ if err != nil {
+ logrus.Debugf("LinkSetName failed for interface %s: %v", i.SrcName(), err)
+ return err
+ }
+
+ // if it is a bridge just delete it.
+ if i.Bridge() {
+ if err := nlh.LinkDel(iface); err != nil {
+ return fmt.Errorf("failed deleting bridge %q: %v", i.SrcName(), err)
+ }
+ } else if !isDefault {
+ // Move the network interface to caller namespace.
+ if err := nlh.LinkSetNsFd(iface, ns.ParseHandlerInt()); err != nil {
+ logrus.Debugf("LinkSetNsPid failed for interface %s: %v", i.SrcName(), err)
+ return err
+ }
+ }
+
+ n.Lock()
+ for index, intf := range n.iFaces {
+ if intf == i {
+ n.iFaces = append(n.iFaces[:index], n.iFaces[index+1:]...)
+ break
+ }
+ }
+ n.Unlock()
+
+ n.checkLoV6()
+
+ return nil
+}
+
+// Returns the sandbox's side veth interface statistics
+func (i *nwIface) Statistics() (*types.InterfaceStatistics, error) {
+ i.Lock()
+ n := i.ns
+ i.Unlock()
+
+ l, err := n.nlHandle.LinkByName(i.DstName())
+ if err != nil {
+ return nil, fmt.Errorf("failed to retrieve the statistics for %s in netns %s: %v", i.DstName(), n.path, err)
+ }
+
+ stats := l.Attrs().Statistics
+ if stats == nil {
+ return nil, fmt.Errorf("no statistics were returned")
+ }
+
+ return &types.InterfaceStatistics{
+ RxBytes: uint64(stats.RxBytes),
+ TxBytes: uint64(stats.TxBytes),
+ RxPackets: uint64(stats.RxPackets),
+ TxPackets: uint64(stats.TxPackets),
+ RxDropped: uint64(stats.RxDropped),
+ TxDropped: uint64(stats.TxDropped),
+ }, nil
+}
+
+func (n *networkNamespace) findDst(srcName string, isBridge bool) string {
+ n.Lock()
+ defer n.Unlock()
+
+ for _, i := range n.iFaces {
+ // The master should match the srcname of the interface and the
+ // master interface should be of type bridge, if searching for a bridge type
+ if i.SrcName() == srcName && (!isBridge || i.Bridge()) {
+ return i.DstName()
+ }
+ }
+
+ return ""
+}
+
+func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error {
+ i := &nwIface{srcName: srcName, dstName: dstPrefix, ns: n}
+ i.processInterfaceOptions(options...)
+
+ if i.master != "" {
+ i.dstMaster = n.findDst(i.master, true)
+ if i.dstMaster == "" {
+ return fmt.Errorf("could not find an appropriate master %q for %q",
+ i.master, i.srcName)
+ }
+ }
+
+ n.Lock()
+ if n.isDefault {
+ i.dstName = i.srcName
+ } else {
+ i.dstName = fmt.Sprintf("%s%d", dstPrefix, n.nextIfIndex[dstPrefix])
+ n.nextIfIndex[dstPrefix]++
+ }
+
+ path := n.path
+ isDefault := n.isDefault
+ nlh := n.nlHandle
+ nlhHost := ns.NlHandle()
+ n.Unlock()
+
+ // If it is a bridge interface we have to create the bridge inside
+ // the namespace so don't try to lookup the interface using srcName
+ if i.bridge {
+ link := &netlink.Bridge{
+ LinkAttrs: netlink.LinkAttrs{
+ Name: i.srcName,
+ },
+ }
+ if err := nlh.LinkAdd(link); err != nil {
+ return fmt.Errorf("failed to create bridge %q: %v", i.srcName, err)
+ }
+ } else {
+ // Find the network interface identified by the SrcName attribute.
+ iface, err := nlhHost.LinkByName(i.srcName)
+ if err != nil {
+ return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err)
+ }
+
+ // Move the network interface to the destination
+ // namespace only if the namespace is not a default
+ // type
+ if !isDefault {
+ newNs, err := netns.GetFromPath(path)
+ if err != nil {
+ return fmt.Errorf("failed get network namespace %q: %v", path, err)
+ }
+ defer newNs.Close()
+ if err := nlhHost.LinkSetNsFd(iface, int(newNs)); err != nil {
+ return fmt.Errorf("failed to set namespace on link %q: %v", i.srcName, err)
+ }
+ }
+ }
+
+ // Find the network interface identified by the SrcName attribute.
+ iface, err := nlh.LinkByName(i.srcName)
+ if err != nil {
+ return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err)
+ }
+
+ // Down the interface before configuring
+ if err := nlh.LinkSetDown(iface); err != nil {
+ return fmt.Errorf("failed to set link down: %v", err)
+ }
+
+ // Configure the interface now this is moved in the proper namespace.
+ if err := configureInterface(nlh, iface, i); err != nil {
+ // If configuring the device fails move it back to the host namespace
+ // and change the name back to the source name. This allows the caller
+ // to properly cleanup the interface. Its important especially for
+ // interfaces with global attributes, ex: vni id for vxlan interfaces.
+ if nerr := nlh.LinkSetName(iface, i.SrcName()); nerr != nil {
+ logrus.Errorf("renaming interface (%s->%s) failed, %v after config error %v", i.DstName(), i.SrcName(), nerr, err)
+ }
+ if nerr := nlh.LinkSetNsFd(iface, ns.ParseHandlerInt()); nerr != nil {
+ logrus.Errorf("moving interface %s to host ns failed, %v, after config error %v", i.SrcName(), nerr, err)
+ }
+ return err
+ }
+
+ // Up the interface.
+ cnt := 0
+ for err = nlh.LinkSetUp(iface); err != nil && cnt < 3; cnt++ {
+ logrus.Debugf("retrying link setup because of: %v", err)
+ time.Sleep(10 * time.Millisecond)
+ err = nlh.LinkSetUp(iface)
+ }
+ if err != nil {
+ return fmt.Errorf("failed to set link up: %v", err)
+ }
+
+ // Set the routes on the interface. This can only be done when the interface is up.
+ if err := setInterfaceRoutes(nlh, iface, i); err != nil {
+ return fmt.Errorf("error setting interface %q routes to %q: %v", iface.Attrs().Name, i.Routes(), err)
+ }
+
+ n.Lock()
+ n.iFaces = append(n.iFaces, i)
+ n.Unlock()
+
+ n.checkLoV6()
+
+ return nil
+}
+
+func configureInterface(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
+ ifaceName := iface.Attrs().Name
+ ifaceConfigurators := []struct {
+ Fn func(*netlink.Handle, netlink.Link, *nwIface) error
+ ErrMessage string
+ }{
+ {setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, i.DstName())},
+ {setInterfaceMAC, fmt.Sprintf("error setting interface %q MAC to %q", ifaceName, i.MacAddress())},
+ {setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %v", ifaceName, i.Address())},
+ {setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %v", ifaceName, i.AddressIPv6())},
+ {setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())},
+ {setInterfaceLinkLocalIPs, fmt.Sprintf("error setting interface %q link local IPs to %v", ifaceName, i.LinkLocalAddresses())},
+ }
+
+ for _, config := range ifaceConfigurators {
+ if err := config.Fn(nlh, iface, i); err != nil {
+ return fmt.Errorf("%s: %v", config.ErrMessage, err)
+ }
+ }
+ return nil
+}
+
+func setInterfaceMaster(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
+ if i.DstMaster() == "" {
+ return nil
+ }
+
+ return nlh.LinkSetMaster(iface, &netlink.Bridge{
+ LinkAttrs: netlink.LinkAttrs{Name: i.DstMaster()}})
+}
+
+func setInterfaceMAC(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
+ if i.MacAddress() == nil {
+ return nil
+ }
+ return nlh.LinkSetHardwareAddr(iface, i.MacAddress())
+}
+
+func setInterfaceIP(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
+ if i.Address() == nil {
+ return nil
+ }
+ if err := checkRouteConflict(nlh, i.Address(), netlink.FAMILY_V4); err != nil {
+ return err
+ }
+ ipAddr := &netlink.Addr{IPNet: i.Address(), Label: ""}
+ return nlh.AddrAdd(iface, ipAddr)
+}
+
+func setInterfaceIPv6(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
+ if i.AddressIPv6() == nil {
+ return nil
+ }
+ if err := checkRouteConflict(nlh, i.AddressIPv6(), netlink.FAMILY_V6); err != nil {
+ return err
+ }
+ if err := setIPv6(i.ns.path, i.DstName(), true); err != nil {
+ return fmt.Errorf("failed to enable ipv6: %v", err)
+ }
+ ipAddr := &netlink.Addr{IPNet: i.AddressIPv6(), Label: "", Flags: syscall.IFA_F_NODAD}
+ return nlh.AddrAdd(iface, ipAddr)
+}
+
+func setInterfaceLinkLocalIPs(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
+ for _, llIP := range i.LinkLocalAddresses() {
+ ipAddr := &netlink.Addr{IPNet: llIP}
+ if err := nlh.AddrAdd(iface, ipAddr); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func setInterfaceName(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
+ return nlh.LinkSetName(iface, i.DstName())
+}
+
+func setInterfaceRoutes(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
+ for _, route := range i.Routes() {
+ err := nlh.RouteAdd(&netlink.Route{
+ Scope: netlink.SCOPE_LINK,
+ LinkIndex: iface.Attrs().Index,
+ Dst: route,
+ })
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// In older kernels (like the one in Centos 6.6 distro) sysctl does not have netns support. Therefore
+// we cannot gather the statistics from /sys/class/net/<dev>/statistics/<counter> files. Per-netns stats
+// are naturally found in /proc/net/dev in kernels which support netns (ifconfig relies on that).
+const (
+ netStatsFile = "/proc/net/dev"
+ base = "[ ]*%s:([ ]+[0-9]+){16}"
+)
+
+func scanInterfaceStats(data, ifName string, i *types.InterfaceStatistics) error {
+ var (
+ bktStr string
+ bkt uint64
+ )
+
+ regex := fmt.Sprintf(base, ifName)
+ re := regexp.MustCompile(regex)
+ line := re.FindString(data)
+
+ _, err := fmt.Sscanf(line, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ &bktStr, &i.RxBytes, &i.RxPackets, &i.RxErrors, &i.RxDropped, &bkt, &bkt, &bkt,
+ &bkt, &i.TxBytes, &i.TxPackets, &i.TxErrors, &i.TxDropped, &bkt, &bkt, &bkt, &bkt)
+
+ return err
+}
+
+func checkRouteConflict(nlh *netlink.Handle, address *net.IPNet, family int) error {
+ routes, err := nlh.RouteList(nil, family)
+ if err != nil {
+ return err
+ }
+ for _, route := range routes {
+ if route.Dst != nil {
+ if route.Dst.Contains(address.IP) || address.Contains(route.Dst.IP) {
+ return fmt.Errorf("cannot program address %v in sandbox interface because it conflicts with existing route %s",
+ address, route)
+ }
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/interface_windows.go b/vendor/github.com/docker/libnetwork/osl/interface_windows.go
new file mode 100644
index 000000000..9c0141fd9
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/interface_windows.go
@@ -0,0 +1,4 @@
+package osl
+
+// IfaceOption is a function option type to set interface options
+type IfaceOption func()
diff --git a/vendor/github.com/docker/libnetwork/osl/kernel/knobs.go b/vendor/github.com/docker/libnetwork/osl/kernel/knobs.go
new file mode 100644
index 000000000..a7cd7dbb7
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/kernel/knobs.go
@@ -0,0 +1,16 @@
+package kernel
+
+type conditionalCheck func(val1, val2 string) bool
+
+// OSValue represents a tuple, value defined, check function when to apply the value
+type OSValue struct {
+ Value string
+ CheckFn conditionalCheck
+}
+
+func propertyIsValid(val1, val2 string, check conditionalCheck) bool {
+ if check == nil || check(val1, val2) {
+ return true
+ }
+ return false
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/kernel/knobs_linux.go b/vendor/github.com/docker/libnetwork/osl/kernel/knobs_linux.go
new file mode 100644
index 000000000..964280650
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/kernel/knobs_linux.go
@@ -0,0 +1,47 @@
+package kernel
+
+import (
+ "io/ioutil"
+ "path"
+ "strings"
+
+ "github.com/sirupsen/logrus"
+)
+
+// writeSystemProperty writes the value to a path under /proc/sys as determined from the key.
+// For e.g. net.ipv4.ip_forward translated to /proc/sys/net/ipv4/ip_forward.
+func writeSystemProperty(key, value string) error {
+ keyPath := strings.Replace(key, ".", "/", -1)
+ return ioutil.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0644)
+}
+
+// readSystemProperty reads the value from the path under /proc/sys and returns it
+func readSystemProperty(key string) (string, error) {
+ keyPath := strings.Replace(key, ".", "/", -1)
+ value, err := ioutil.ReadFile(path.Join("/proc/sys", keyPath))
+ if err != nil {
+ return "", err
+ }
+ return strings.TrimSpace(string(value)), nil
+}
+
+// ApplyOSTweaks applies the configuration values passed as arguments
+func ApplyOSTweaks(osConfig map[string]*OSValue) {
+ for k, v := range osConfig {
+ // read the existing property from disk
+ oldv, err := readSystemProperty(k)
+ if err != nil {
+ logrus.WithError(err).Errorf("error reading the kernel parameter %s", k)
+ continue
+ }
+
+ if propertyIsValid(oldv, v.Value, v.CheckFn) {
+ // write new prop value to disk
+ if err := writeSystemProperty(k, v.Value); err != nil {
+ logrus.WithError(err).Errorf("error setting the kernel parameter %s = %s, (leaving as %s)", k, v.Value, oldv)
+ continue
+ }
+ logrus.Debugf("updated kernel parameter %s = %s (was %s)", k, v.Value, oldv)
+ }
+ }
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/kernel/knobs_unsupported.go b/vendor/github.com/docker/libnetwork/osl/kernel/knobs_unsupported.go
new file mode 100644
index 000000000..32f258f41
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/kernel/knobs_unsupported.go
@@ -0,0 +1,7 @@
+// +build !linux
+
+package kernel
+
+// ApplyOSTweaks applies the configuration values passed as arguments
+func ApplyOSTweaks(osConfig map[string]*OSValue) {
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
new file mode 100644
index 000000000..abb748b56
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
@@ -0,0 +1,657 @@
+package osl
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/docker/docker/pkg/reexec"
+ "github.com/docker/libnetwork/ns"
+ "github.com/docker/libnetwork/osl/kernel"
+ "github.com/docker/libnetwork/types"
+ "github.com/sirupsen/logrus"
+ "github.com/vishvananda/netlink"
+ "github.com/vishvananda/netns"
+)
+
+const defaultPrefix = "/var/run/docker"
+
+func init() {
+ reexec.Register("set-ipv6", reexecSetIPv6)
+}
+
+var (
+ once sync.Once
+ garbagePathMap = make(map[string]bool)
+ gpmLock sync.Mutex
+ gpmWg sync.WaitGroup
+ gpmCleanupPeriod = 60 * time.Second
+ gpmChan = make(chan chan struct{})
+ prefix = defaultPrefix
+ loadBalancerConfig = map[string]*kernel.OSValue{
+ // expires connection from the IPVS connection table when the backend is not available
+ // more info: https://github.com/torvalds/linux/blob/master/Documentation/networking/ipvs-sysctl.txt#L126:1
+ "net.ipv4.vs.expire_nodest_conn": {"1", nil},
+ }
+)
+
+// The networkNamespace type is the linux implementation of the Sandbox
+// interface. It represents a linux network namespace, and moves an interface
+// into it when called on method AddInterface or sets the gateway etc.
+type networkNamespace struct {
+ path string
+ iFaces []*nwIface
+ gw net.IP
+ gwv6 net.IP
+ staticRoutes []*types.StaticRoute
+ neighbors []*neigh
+ nextIfIndex map[string]int
+ isDefault bool
+ nlHandle *netlink.Handle
+ loV6Enabled bool
+ sync.Mutex
+}
+
+// SetBasePath sets the base url prefix for the ns path
+func SetBasePath(path string) {
+ prefix = path
+}
+
+func init() {
+ reexec.Register("netns-create", reexecCreateNamespace)
+}
+
+func basePath() string {
+ return filepath.Join(prefix, "netns")
+}
+
+func createBasePath() {
+ err := os.MkdirAll(basePath(), 0755)
+ if err != nil {
+ panic("Could not create net namespace path directory")
+ }
+
+ // Start the garbage collection go routine
+ go removeUnusedPaths()
+}
+
+func removeUnusedPaths() {
+ gpmLock.Lock()
+ period := gpmCleanupPeriod
+ gpmLock.Unlock()
+
+ ticker := time.NewTicker(period)
+ for {
+ var (
+ gc chan struct{}
+ gcOk bool
+ )
+
+ select {
+ case <-ticker.C:
+ case gc, gcOk = <-gpmChan:
+ }
+
+ gpmLock.Lock()
+ pathList := make([]string, 0, len(garbagePathMap))
+ for path := range garbagePathMap {
+ pathList = append(pathList, path)
+ }
+ garbagePathMap = make(map[string]bool)
+ gpmWg.Add(1)
+ gpmLock.Unlock()
+
+ for _, path := range pathList {
+ os.Remove(path)
+ }
+
+ gpmWg.Done()
+ if gcOk {
+ close(gc)
+ }
+ }
+}
+
+func addToGarbagePaths(path string) {
+ gpmLock.Lock()
+ garbagePathMap[path] = true
+ gpmLock.Unlock()
+}
+
+func removeFromGarbagePaths(path string) {
+ gpmLock.Lock()
+ delete(garbagePathMap, path)
+ gpmLock.Unlock()
+}
+
+// GC triggers garbage collection of namespace path right away
+// and waits for it.
+func GC() {
+ gpmLock.Lock()
+ if len(garbagePathMap) == 0 {
+ // No need for GC if map is empty
+ gpmLock.Unlock()
+ return
+ }
+ gpmLock.Unlock()
+
+ // if content exists in the garbage paths
+ // we can trigger GC to run, providing a
+ // channel to be notified on completion
+ waitGC := make(chan struct{})
+ gpmChan <- waitGC
+ // wait for GC completion
+ <-waitGC
+}
+
+// GenerateKey generates a sandbox key based on the passed
+// container id.
+func GenerateKey(containerID string) string {
+ maxLen := 12
+ // Read sandbox key from host for overlay
+ if strings.HasPrefix(containerID, "-") {
+ var (
+ index int
+ indexStr string
+ tmpkey string
+ )
+ dir, err := ioutil.ReadDir(basePath())
+ if err != nil {
+ return ""
+ }
+
+ for _, v := range dir {
+ id := v.Name()
+ if strings.HasSuffix(id, containerID[:maxLen-1]) {
+ indexStr = strings.TrimSuffix(id, containerID[:maxLen-1])
+ tmpindex, err := strconv.Atoi(indexStr)
+ if err != nil {
+ return ""
+ }
+ if tmpindex > index {
+ index = tmpindex
+ tmpkey = id
+ }
+
+ }
+ }
+ containerID = tmpkey
+ if containerID == "" {
+ return ""
+ }
+ }
+
+ if len(containerID) < maxLen {
+ maxLen = len(containerID)
+ }
+
+ return basePath() + "/" + containerID[:maxLen]
+}
+
+// NewSandbox provides a new sandbox instance created in an os specific way
+// provided a key which uniquely identifies the sandbox
+func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
+ if !isRestore {
+ err := createNetworkNamespace(key, osCreate)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ once.Do(createBasePath)
+ }
+
+ n := &networkNamespace{path: key, isDefault: !osCreate, nextIfIndex: make(map[string]int)}
+
+ sboxNs, err := netns.GetFromPath(n.path)
+ if err != nil {
+ return nil, fmt.Errorf("failed get network namespace %q: %v", n.path, err)
+ }
+ defer sboxNs.Close()
+
+ n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
+ }
+
+ err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
+ if err != nil {
+ logrus.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
+ }
+ // In live-restore mode, IPV6 entries are getting cleaned up due to below code
+ // We should retain IPV6 configurations in live-restore mode when Docker Daemon
+ // comes back. It should work as it is on other cases
+ // As starting point, disable IPv6 on all interfaces
+ if !isRestore && !n.isDefault {
+ err = setIPv6(n.path, "all", false)
+ if err != nil {
+ logrus.Warnf("Failed to disable IPv6 on all interfaces on network namespace %q: %v", n.path, err)
+ }
+ }
+
+ if err = n.loopbackUp(); err != nil {
+ n.nlHandle.Delete()
+ return nil, err
+ }
+
+ return n, nil
+}
+
+func (n *networkNamespace) InterfaceOptions() IfaceOptionSetter {
+ return n
+}
+
+func (n *networkNamespace) NeighborOptions() NeighborOptionSetter {
+ return n
+}
+
+func mountNetworkNamespace(basePath string, lnPath string) error {
+ return syscall.Mount(basePath, lnPath, "bind", syscall.MS_BIND, "")
+}
+
+// GetSandboxForExternalKey returns sandbox object for the supplied path
+func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) {
+ if err := createNamespaceFile(key); err != nil {
+ return nil, err
+ }
+
+ if err := mountNetworkNamespace(basePath, key); err != nil {
+ return nil, err
+ }
+ n := &networkNamespace{path: key, nextIfIndex: make(map[string]int)}
+
+ sboxNs, err := netns.GetFromPath(n.path)
+ if err != nil {
+ return nil, fmt.Errorf("failed get network namespace %q: %v", n.path, err)
+ }
+ defer sboxNs.Close()
+
+ n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
+ }
+
+ err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
+ if err != nil {
+ logrus.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
+ }
+
+ // As starting point, disable IPv6 on all interfaces
+ err = setIPv6(n.path, "all", false)
+ if err != nil {
+ logrus.Warnf("Failed to disable IPv6 on all interfaces on network namespace %q: %v", n.path, err)
+ }
+
+ if err = n.loopbackUp(); err != nil {
+ n.nlHandle.Delete()
+ return nil, err
+ }
+
+ return n, nil
+}
+
+func reexecCreateNamespace() {
+ if len(os.Args) < 2 {
+ logrus.Fatal("no namespace path provided")
+ }
+ if err := mountNetworkNamespace("/proc/self/ns/net", os.Args[1]); err != nil {
+ logrus.Fatal(err)
+ }
+}
+
+func createNetworkNamespace(path string, osCreate bool) error {
+ if err := createNamespaceFile(path); err != nil {
+ return err
+ }
+
+ cmd := &exec.Cmd{
+ Path: reexec.Self(),
+ Args: append([]string{"netns-create"}, path),
+ Stdout: os.Stdout,
+ Stderr: os.Stderr,
+ }
+ if osCreate {
+ cmd.SysProcAttr = &syscall.SysProcAttr{}
+ cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWNET
+ }
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("namespace creation reexec command failed: %v", err)
+ }
+
+ return nil
+}
+
+func unmountNamespaceFile(path string) {
+ if _, err := os.Stat(path); err == nil {
+ syscall.Unmount(path, syscall.MNT_DETACH)
+ }
+}
+
+func createNamespaceFile(path string) (err error) {
+ var f *os.File
+
+ once.Do(createBasePath)
+ // Remove it from garbage collection list if present
+ removeFromGarbagePaths(path)
+
+ // If the path is there unmount it first
+ unmountNamespaceFile(path)
+
+ // wait for garbage collection to complete if it is in progress
+ // before trying to create the file.
+ gpmWg.Wait()
+
+ if f, err = os.Create(path); err == nil {
+ f.Close()
+ }
+
+ return err
+}
+
+func (n *networkNamespace) loopbackUp() error {
+ iface, err := n.nlHandle.LinkByName("lo")
+ if err != nil {
+ return err
+ }
+ return n.nlHandle.LinkSetUp(iface)
+}
+
+func (n *networkNamespace) GetLoopbackIfaceName() string {
+ return "lo"
+}
+
+func (n *networkNamespace) AddAliasIP(ifName string, ip *net.IPNet) error {
+ iface, err := n.nlHandle.LinkByName(ifName)
+ if err != nil {
+ return err
+ }
+ return n.nlHandle.AddrAdd(iface, &netlink.Addr{IPNet: ip})
+}
+
+func (n *networkNamespace) RemoveAliasIP(ifName string, ip *net.IPNet) error {
+ iface, err := n.nlHandle.LinkByName(ifName)
+ if err != nil {
+ return err
+ }
+ return n.nlHandle.AddrDel(iface, &netlink.Addr{IPNet: ip})
+}
+
+func (n *networkNamespace) InvokeFunc(f func()) error {
+ return nsInvoke(n.nsPath(), func(nsFD int) error { return nil }, func(callerFD int) error {
+ f()
+ return nil
+ })
+}
+
+// InitOSContext initializes OS context while configuring network resources
+func InitOSContext() func() {
+ runtime.LockOSThread()
+ if err := ns.SetNamespace(); err != nil {
+ logrus.Error(err)
+ }
+ return runtime.UnlockOSThread
+}
+
+func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error {
+ defer InitOSContext()()
+
+ newNs, err := netns.GetFromPath(path)
+ if err != nil {
+ return fmt.Errorf("failed get network namespace %q: %v", path, err)
+ }
+ defer newNs.Close()
+
+ // Invoked before the namespace switch happens but after the namespace file
+ // handle is obtained.
+ if err := prefunc(int(newNs)); err != nil {
+ return fmt.Errorf("failed in prefunc: %v", err)
+ }
+
+ if err = netns.Set(newNs); err != nil {
+ return err
+ }
+ defer ns.SetNamespace()
+
+ // Invoked after the namespace switch.
+ return postfunc(ns.ParseHandlerInt())
+}
+
+func (n *networkNamespace) nsPath() string {
+ n.Lock()
+ defer n.Unlock()
+
+ return n.path
+}
+
+func (n *networkNamespace) Info() Info {
+ return n
+}
+
+func (n *networkNamespace) Key() string {
+ return n.path
+}
+
+func (n *networkNamespace) Destroy() error {
+ if n.nlHandle != nil {
+ n.nlHandle.Delete()
+ }
+ // Assuming no running process is executing in this network namespace,
+ // unmounting is sufficient to destroy it.
+ if err := syscall.Unmount(n.path, syscall.MNT_DETACH); err != nil {
+ return err
+ }
+
+ // Stash it into the garbage collection list
+ addToGarbagePaths(n.path)
+ return nil
+}
+
+// Restore restore the network namespace
+func (n *networkNamespace) Restore(ifsopt map[string][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error {
+ // restore interfaces
+ for name, opts := range ifsopt {
+ if !strings.Contains(name, "+") {
+ return fmt.Errorf("wrong iface name in restore osl sandbox interface: %s", name)
+ }
+ seps := strings.Split(name, "+")
+ srcName := seps[0]
+ dstPrefix := seps[1]
+ i := &nwIface{srcName: srcName, dstName: dstPrefix, ns: n}
+ i.processInterfaceOptions(opts...)
+ if i.master != "" {
+ i.dstMaster = n.findDst(i.master, true)
+ if i.dstMaster == "" {
+ return fmt.Errorf("could not find an appropriate master %q for %q",
+ i.master, i.srcName)
+ }
+ }
+ if n.isDefault {
+ i.dstName = i.srcName
+ } else {
+ links, err := n.nlHandle.LinkList()
+ if err != nil {
+ return fmt.Errorf("failed to retrieve list of links in network namespace %q during restore", n.path)
+ }
+ // due to the docker network connect/disconnect, so the dstName should
+ // restore from the namespace
+ for _, link := range links {
+ addrs, err := n.nlHandle.AddrList(link, netlink.FAMILY_V4)
+ if err != nil {
+ return err
+ }
+ ifaceName := link.Attrs().Name
+ if strings.HasPrefix(ifaceName, "vxlan") {
+ if i.dstName == "vxlan" {
+ i.dstName = ifaceName
+ break
+ }
+ }
+ // find the interface name by ip
+ if i.address != nil {
+ for _, addr := range addrs {
+ if addr.IPNet.String() == i.address.String() {
+ i.dstName = ifaceName
+ break
+ }
+ continue
+ }
+ if i.dstName == ifaceName {
+ break
+ }
+ }
+ // This is to find the interface name of the pair in overlay sandbox
+ if strings.HasPrefix(ifaceName, "veth") {
+ if i.master != "" && i.dstName == "veth" {
+ i.dstName = ifaceName
+ }
+ }
+ }
+
+ var index int
+ indexStr := strings.TrimPrefix(i.dstName, dstPrefix)
+ if indexStr != "" {
+ index, err = strconv.Atoi(indexStr)
+ if err != nil {
+ return err
+ }
+ }
+ index++
+ n.Lock()
+ if index > n.nextIfIndex[dstPrefix] {
+ n.nextIfIndex[dstPrefix] = index
+ }
+ n.iFaces = append(n.iFaces, i)
+ n.Unlock()
+ }
+ }
+
+ // restore routes
+ for _, r := range routes {
+ n.Lock()
+ n.staticRoutes = append(n.staticRoutes, r)
+ n.Unlock()
+ }
+
+ // restore gateway
+ if len(gw) > 0 {
+ n.Lock()
+ n.gw = gw
+ n.Unlock()
+ }
+
+ if len(gw6) > 0 {
+ n.Lock()
+ n.gwv6 = gw6
+ n.Unlock()
+ }
+
+ return nil
+}
+
+// Checks whether IPv6 needs to be enabled/disabled on the loopback interface
+func (n *networkNamespace) checkLoV6() {
+ var (
+ enable = false
+ action = "disable"
+ )
+
+ n.Lock()
+ for _, iface := range n.iFaces {
+ if iface.AddressIPv6() != nil {
+ enable = true
+ action = "enable"
+ break
+ }
+ }
+ n.Unlock()
+
+ if n.loV6Enabled == enable {
+ return
+ }
+
+ if err := setIPv6(n.path, "lo", enable); err != nil {
+ logrus.Warnf("Failed to %s IPv6 on loopback interface on network namespace %q: %v", action, n.path, err)
+ }
+
+ n.loV6Enabled = enable
+}
+
+func reexecSetIPv6() {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if len(os.Args) < 3 {
+ logrus.Errorf("invalid number of arguments for %s", os.Args[0])
+ os.Exit(1)
+ }
+
+ ns, err := netns.GetFromPath(os.Args[1])
+ if err != nil {
+ logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err)
+ os.Exit(2)
+ }
+ defer ns.Close()
+
+ if err = netns.Set(ns); err != nil {
+ logrus.Errorf("setting into container netns %q failed: %v", os.Args[1], err)
+ os.Exit(3)
+ }
+
+ var (
+ action = "disable"
+ value = byte('1')
+ path = fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", os.Args[2])
+ )
+
+ if os.Args[3] == "true" {
+ action = "enable"
+ value = byte('0')
+ }
+
+ if _, err := os.Stat(path); err != nil {
+ if os.IsNotExist(err) {
+ logrus.Warnf("file does not exist: %s : %v Has IPv6 been disabled in this node's kernel?", path, err)
+ os.Exit(0)
+ }
+ logrus.Errorf("failed to stat %s : %v", path, err)
+ os.Exit(5)
+ }
+
+ if err = ioutil.WriteFile(path, []byte{value, '\n'}, 0644); err != nil {
+ logrus.Errorf("failed to %s IPv6 forwarding for container's interface %s: %v", action, os.Args[2], err)
+ os.Exit(4)
+ }
+
+ os.Exit(0)
+}
+
+func setIPv6(path, iface string, enable bool) error {
+ cmd := &exec.Cmd{
+ Path: reexec.Self(),
+ Args: append([]string{"set-ipv6"}, path, iface, strconv.FormatBool(enable)),
+ Stdout: os.Stdout,
+ Stderr: os.Stderr,
+ }
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("reexec to set IPv6 failed: %v", err)
+ }
+ return nil
+}
+
+// ApplyOSTweaks applies linux configs on the sandbox
+func (n *networkNamespace) ApplyOSTweaks(types []SandboxType) {
+ for _, t := range types {
+ switch t {
+ case SandboxTypeLoadBalancer:
+ kernel.ApplyOSTweaks(loadBalancerConfig)
+ }
+ }
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/namespace_unsupported.go b/vendor/github.com/docker/libnetwork/osl/namespace_unsupported.go
new file mode 100644
index 000000000..74372e249
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/namespace_unsupported.go
@@ -0,0 +1,17 @@
+// +build !linux,!windows,!freebsd
+
+package osl
+
+// GC triggers garbage collection of namespace path right away
+// and waits for it.
+func GC() {
+}
+
+// GetSandboxForExternalKey returns sandbox object for the supplied path
+func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
+ return nil, nil
+}
+
+// SetBasePath sets the base url prefix for the ns path
+func SetBasePath(path string) {
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/namespace_windows.go b/vendor/github.com/docker/libnetwork/osl/namespace_windows.go
new file mode 100644
index 000000000..49503c00f
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/namespace_windows.go
@@ -0,0 +1,38 @@
+package osl
+
+import "testing"
+
+// GenerateKey generates a sandbox key based on the passed
+// container id.
+func GenerateKey(containerID string) string {
+ return containerID
+}
+
+// NewSandbox provides a new sandbox instance created in an os specific way
+// provided a key which uniquely identifies the sandbox
+func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
+ return nil, nil
+}
+
+func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
+ return nil, nil
+}
+
+// GC triggers garbage collection of namespace path right away
+// and waits for it.
+func GC() {
+}
+
+// InitOSContext initializes OS context while configuring network resources
+func InitOSContext() func() {
+ return func() {}
+}
+
+// SetupTestOSContext sets up a separate test OS context in which tests will be executed.
+func SetupTestOSContext(t *testing.T) func() {
+ return func() {}
+}
+
+// SetBasePath sets the base url prefix for the ns path
+func SetBasePath(path string) {
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/neigh_freebsd.go b/vendor/github.com/docker/libnetwork/osl/neigh_freebsd.go
new file mode 100644
index 000000000..280f00639
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/neigh_freebsd.go
@@ -0,0 +1,4 @@
+package osl
+
+// NeighOption is a function option type to set neighbor options
+type NeighOption func()
diff --git a/vendor/github.com/docker/libnetwork/osl/neigh_linux.go b/vendor/github.com/docker/libnetwork/osl/neigh_linux.go
new file mode 100644
index 000000000..6bf1c16dc
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/neigh_linux.go
@@ -0,0 +1,194 @@
+package osl
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+
+ "github.com/sirupsen/logrus"
+ "github.com/vishvananda/netlink"
+)
+
+// NeighborSearchError indicates that the neighbor is already present
+type NeighborSearchError struct {
+ ip net.IP
+ mac net.HardwareAddr
+ present bool
+}
+
+func (n NeighborSearchError) Error() string {
+ return fmt.Sprintf("Search neighbor failed for IP %v, mac %v, present in db:%t", n.ip, n.mac, n.present)
+}
+
+// NeighOption is a function option type to set interface options
+type NeighOption func(nh *neigh)
+
+type neigh struct {
+ dstIP net.IP
+ dstMac net.HardwareAddr
+ linkName string
+ linkDst string
+ family int
+}
+
+func (n *networkNamespace) findNeighbor(dstIP net.IP, dstMac net.HardwareAddr) *neigh {
+ n.Lock()
+ defer n.Unlock()
+
+ for _, nh := range n.neighbors {
+ if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
+ return nh
+ }
+ }
+
+ return nil
+}
+
+func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error {
+ var (
+ iface netlink.Link
+ err error
+ )
+
+ nh := n.findNeighbor(dstIP, dstMac)
+ if nh == nil {
+ return NeighborSearchError{dstIP, dstMac, false}
+ }
+
+ if osDelete {
+ n.Lock()
+ nlh := n.nlHandle
+ n.Unlock()
+
+ if nh.linkDst != "" {
+ iface, err = nlh.LinkByName(nh.linkDst)
+ if err != nil {
+ return fmt.Errorf("could not find interface with destination name %s: %v",
+ nh.linkDst, err)
+ }
+ }
+
+ nlnh := &netlink.Neigh{
+ IP: dstIP,
+ State: netlink.NUD_PERMANENT,
+ Family: nh.family,
+ }
+
+ if nlnh.Family > 0 {
+ nlnh.HardwareAddr = dstMac
+ nlnh.Flags = netlink.NTF_SELF
+ }
+
+ if nh.linkDst != "" {
+ nlnh.LinkIndex = iface.Attrs().Index
+ }
+
+ // If the kernel deletion fails for the neighbor entry still remote it
+ // from the namespace cache. Otherwise if the neighbor moves back to the
+ // same host again, kernel update can fail.
+ if err := nlh.NeighDel(nlnh); err != nil {
+ logrus.Warnf("Deleting neighbor IP %s, mac %s failed, %v", dstIP, dstMac, err)
+ }
+
+ // Delete the dynamic entry in the bridge
+ if nlnh.Family > 0 {
+ nlnh := &netlink.Neigh{
+ IP: dstIP,
+ Family: nh.family,
+ }
+
+ nlnh.HardwareAddr = dstMac
+ nlnh.Flags = netlink.NTF_MASTER
+ if nh.linkDst != "" {
+ nlnh.LinkIndex = iface.Attrs().Index
+ }
+ nlh.NeighDel(nlnh)
+ }
+ }
+
+ n.Lock()
+ for i, nh := range n.neighbors {
+ if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
+ n.neighbors = append(n.neighbors[:i], n.neighbors[i+1:]...)
+ break
+ }
+ }
+ n.Unlock()
+ logrus.Debugf("Neighbor entry deleted for IP %v, mac %v osDelete:%t", dstIP, dstMac, osDelete)
+
+ return nil
+}
+
+func (n *networkNamespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, force bool, options ...NeighOption) error {
+ var (
+ iface netlink.Link
+ err error
+ neighborAlreadyPresent bool
+ )
+
+ // If the namespace already has the neighbor entry but the AddNeighbor is called
+ // because of a miss notification (force flag) program the kernel anyway.
+ nh := n.findNeighbor(dstIP, dstMac)
+ if nh != nil {
+ neighborAlreadyPresent = true
+ logrus.Warnf("Neighbor entry already present for IP %v, mac %v neighbor:%+v forceUpdate:%t", dstIP, dstMac, nh, force)
+ if !force {
+ return NeighborSearchError{dstIP, dstMac, true}
+ }
+ }
+
+ nh = &neigh{
+ dstIP: dstIP,
+ dstMac: dstMac,
+ }
+
+ nh.processNeighOptions(options...)
+
+ if nh.linkName != "" {
+ nh.linkDst = n.findDst(nh.linkName, false)
+ if nh.linkDst == "" {
+ return fmt.Errorf("could not find the interface with name %s", nh.linkName)
+ }
+ }
+
+ n.Lock()
+ nlh := n.nlHandle
+ n.Unlock()
+
+ if nh.linkDst != "" {
+ iface, err = nlh.LinkByName(nh.linkDst)
+ if err != nil {
+ return fmt.Errorf("could not find interface with destination name %s: %v", nh.linkDst, err)
+ }
+ }
+
+ nlnh := &netlink.Neigh{
+ IP: dstIP,
+ HardwareAddr: dstMac,
+ State: netlink.NUD_PERMANENT,
+ Family: nh.family,
+ }
+
+ if nlnh.Family > 0 {
+ nlnh.Flags = netlink.NTF_SELF
+ }
+
+ if nh.linkDst != "" {
+ nlnh.LinkIndex = iface.Attrs().Index
+ }
+
+ if err := nlh.NeighSet(nlnh); err != nil {
+ return fmt.Errorf("could not add neighbor entry:%+v error:%v", nlnh, err)
+ }
+
+ if neighborAlreadyPresent {
+ return nil
+ }
+
+ n.Lock()
+ n.neighbors = append(n.neighbors, nh)
+ n.Unlock()
+ logrus.Debugf("Neighbor entry added for IP:%v, mac:%v on ifc:%s", dstIP, dstMac, nh.linkName)
+
+ return nil
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/neigh_windows.go b/vendor/github.com/docker/libnetwork/osl/neigh_windows.go
new file mode 100644
index 000000000..280f00639
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/neigh_windows.go
@@ -0,0 +1,4 @@
+package osl
+
+// NeighOption is a function option type to set neighbor options
+type NeighOption func()
diff --git a/vendor/github.com/docker/libnetwork/osl/options_linux.go b/vendor/github.com/docker/libnetwork/osl/options_linux.go
new file mode 100644
index 000000000..818669647
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/options_linux.go
@@ -0,0 +1,73 @@
+package osl
+
+import "net"
+
+func (nh *neigh) processNeighOptions(options ...NeighOption) {
+ for _, opt := range options {
+ if opt != nil {
+ opt(nh)
+ }
+ }
+}
+
+func (n *networkNamespace) LinkName(name string) NeighOption {
+ return func(nh *neigh) {
+ nh.linkName = name
+ }
+}
+
+func (n *networkNamespace) Family(family int) NeighOption {
+ return func(nh *neigh) {
+ nh.family = family
+ }
+}
+
+func (i *nwIface) processInterfaceOptions(options ...IfaceOption) {
+ for _, opt := range options {
+ if opt != nil {
+ opt(i)
+ }
+ }
+}
+
+func (n *networkNamespace) Bridge(isBridge bool) IfaceOption {
+ return func(i *nwIface) {
+ i.bridge = isBridge
+ }
+}
+
+func (n *networkNamespace) Master(name string) IfaceOption {
+ return func(i *nwIface) {
+ i.master = name
+ }
+}
+
+func (n *networkNamespace) MacAddress(mac net.HardwareAddr) IfaceOption {
+ return func(i *nwIface) {
+ i.mac = mac
+ }
+}
+
+func (n *networkNamespace) Address(addr *net.IPNet) IfaceOption {
+ return func(i *nwIface) {
+ i.address = addr
+ }
+}
+
+func (n *networkNamespace) AddressIPv6(addr *net.IPNet) IfaceOption {
+ return func(i *nwIface) {
+ i.addressIPv6 = addr
+ }
+}
+
+func (n *networkNamespace) LinkLocalAddresses(list []*net.IPNet) IfaceOption {
+ return func(i *nwIface) {
+ i.llAddrs = list
+ }
+}
+
+func (n *networkNamespace) Routes(routes []*net.IPNet) IfaceOption {
+ return func(i *nwIface) {
+ i.routes = routes
+ }
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/route_linux.go b/vendor/github.com/docker/libnetwork/osl/route_linux.go
new file mode 100644
index 000000000..a9ff191b3
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/route_linux.go
@@ -0,0 +1,203 @@
+package osl
+
+import (
+ "fmt"
+ "net"
+
+ "github.com/docker/libnetwork/types"
+ "github.com/vishvananda/netlink"
+)
+
+func (n *networkNamespace) Gateway() net.IP {
+ n.Lock()
+ defer n.Unlock()
+
+ return n.gw
+}
+
+func (n *networkNamespace) GatewayIPv6() net.IP {
+ n.Lock()
+ defer n.Unlock()
+
+ return n.gwv6
+}
+
+func (n *networkNamespace) StaticRoutes() []*types.StaticRoute {
+ n.Lock()
+ defer n.Unlock()
+
+ routes := make([]*types.StaticRoute, len(n.staticRoutes))
+ for i, route := range n.staticRoutes {
+ r := route.GetCopy()
+ routes[i] = r
+ }
+
+ return routes
+}
+
+func (n *networkNamespace) setGateway(gw net.IP) {
+ n.Lock()
+ n.gw = gw
+ n.Unlock()
+}
+
+func (n *networkNamespace) setGatewayIPv6(gwv6 net.IP) {
+ n.Lock()
+ n.gwv6 = gwv6
+ n.Unlock()
+}
+
+func (n *networkNamespace) SetGateway(gw net.IP) error {
+ // Silently return if the gateway is empty
+ if len(gw) == 0 {
+ return nil
+ }
+
+ err := n.programGateway(gw, true)
+ if err == nil {
+ n.setGateway(gw)
+ }
+
+ return err
+}
+
+func (n *networkNamespace) UnsetGateway() error {
+ gw := n.Gateway()
+
+ // Silently return if the gateway is empty
+ if len(gw) == 0 {
+ return nil
+ }
+
+ err := n.programGateway(gw, false)
+ if err == nil {
+ n.setGateway(net.IP{})
+ }
+
+ return err
+}
+
+func (n *networkNamespace) programGateway(gw net.IP, isAdd bool) error {
+ gwRoutes, err := n.nlHandle.RouteGet(gw)
+ if err != nil {
+ return fmt.Errorf("route for the gateway %s could not be found: %v", gw, err)
+ }
+
+ var linkIndex int
+ for _, gwRoute := range gwRoutes {
+ if gwRoute.Gw == nil {
+ linkIndex = gwRoute.LinkIndex
+ break
+ }
+ }
+
+ if linkIndex == 0 {
+ return fmt.Errorf("Direct route for the gateway %s could not be found", gw)
+ }
+
+ if isAdd {
+ return n.nlHandle.RouteAdd(&netlink.Route{
+ Scope: netlink.SCOPE_UNIVERSE,
+ LinkIndex: linkIndex,
+ Gw: gw,
+ })
+ }
+
+ return n.nlHandle.RouteDel(&netlink.Route{
+ Scope: netlink.SCOPE_UNIVERSE,
+ LinkIndex: linkIndex,
+ Gw: gw,
+ })
+}
+
+// Program a route in to the namespace routing table.
+func (n *networkNamespace) programRoute(path string, dest *net.IPNet, nh net.IP) error {
+ gwRoutes, err := n.nlHandle.RouteGet(nh)
+ if err != nil {
+ return fmt.Errorf("route for the next hop %s could not be found: %v", nh, err)
+ }
+
+ return n.nlHandle.RouteAdd(&netlink.Route{
+ Scope: netlink.SCOPE_UNIVERSE,
+ LinkIndex: gwRoutes[0].LinkIndex,
+ Gw: nh,
+ Dst: dest,
+ })
+}
+
+// Delete a route from the namespace routing table.
+func (n *networkNamespace) removeRoute(path string, dest *net.IPNet, nh net.IP) error {
+ gwRoutes, err := n.nlHandle.RouteGet(nh)
+ if err != nil {
+ return fmt.Errorf("route for the next hop could not be found: %v", err)
+ }
+
+ return n.nlHandle.RouteDel(&netlink.Route{
+ Scope: netlink.SCOPE_UNIVERSE,
+ LinkIndex: gwRoutes[0].LinkIndex,
+ Gw: nh,
+ Dst: dest,
+ })
+}
+
+func (n *networkNamespace) SetGatewayIPv6(gwv6 net.IP) error {
+ // Silently return if the gateway is empty
+ if len(gwv6) == 0 {
+ return nil
+ }
+
+ err := n.programGateway(gwv6, true)
+ if err == nil {
+ n.setGatewayIPv6(gwv6)
+ }
+
+ return err
+}
+
+func (n *networkNamespace) UnsetGatewayIPv6() error {
+ gwv6 := n.GatewayIPv6()
+
+ // Silently return if the gateway is empty
+ if len(gwv6) == 0 {
+ return nil
+ }
+
+ err := n.programGateway(gwv6, false)
+ if err == nil {
+ n.Lock()
+ n.gwv6 = net.IP{}
+ n.Unlock()
+ }
+
+ return err
+}
+
+func (n *networkNamespace) AddStaticRoute(r *types.StaticRoute) error {
+ err := n.programRoute(n.nsPath(), r.Destination, r.NextHop)
+ if err == nil {
+ n.Lock()
+ n.staticRoutes = append(n.staticRoutes, r)
+ n.Unlock()
+ }
+ return err
+}
+
+func (n *networkNamespace) RemoveStaticRoute(r *types.StaticRoute) error {
+
+ err := n.removeRoute(n.nsPath(), r.Destination, r.NextHop)
+ if err == nil {
+ n.Lock()
+ lastIndex := len(n.staticRoutes) - 1
+ for i, v := range n.staticRoutes {
+ if v == r {
+ // Overwrite the route we're removing with the last element
+ n.staticRoutes[i] = n.staticRoutes[lastIndex]
+ // Shorten the slice to trim the extra element
+ n.staticRoutes = n.staticRoutes[:lastIndex]
+ break
+ }
+ }
+ n.Unlock()
+ }
+ return err
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/sandbox.go b/vendor/github.com/docker/libnetwork/osl/sandbox.go
new file mode 100644
index 000000000..5019e068d
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/sandbox.go
@@ -0,0 +1,187 @@
+// Package osl describes structures and interfaces which abstract os entities
+package osl
+
+import (
+ "net"
+
+ "github.com/docker/libnetwork/types"
+)
+
+// SandboxType specify the time of the sandbox, this can be used to apply special configs
+type SandboxType int
+
+const (
+ // SandboxTypeIngress indicates that the sandbox is for the ingress
+ SandboxTypeIngress = iota
+ // SandboxTypeLoadBalancer indicates that the sandbox is a load balancer
+ SandboxTypeLoadBalancer = iota
+)
+
+// Sandbox represents a network sandbox, identified by a specific key. It
+// holds a list of Interfaces, routes etc, and more can be added dynamically.
+type Sandbox interface {
+ // The path where the network namespace is mounted.
+ Key() string
+
+ // Add an existing Interface to this sandbox. The operation will rename
+ // from the Interface SrcName to DstName as it moves, and reconfigure the
+ // interface according to the specified settings. The caller is expected
+ // to only provide a prefix for DstName. The AddInterface api will auto-generate
+ // an appropriate suffix for the DstName to disambiguate.
+ AddInterface(SrcName string, DstPrefix string, options ...IfaceOption) error
+
+ // Set default IPv4 gateway for the sandbox
+ SetGateway(gw net.IP) error
+
+ // Set default IPv6 gateway for the sandbox
+ SetGatewayIPv6(gw net.IP) error
+
+ // Unset the previously set default IPv4 gateway in the sandbox
+ UnsetGateway() error
+
+ // Unset the previously set default IPv6 gateway in the sandbox
+ UnsetGatewayIPv6() error
+
+ // GetLoopbackIfaceName returns the name of the loopback interface
+ GetLoopbackIfaceName() string
+
+ // AddAliasIP adds the passed IP address to the named interface
+ AddAliasIP(ifName string, ip *net.IPNet) error
+
+ // RemoveAliasIP removes the passed IP address from the named interface
+ RemoveAliasIP(ifName string, ip *net.IPNet) error
+
+ // Add a static route to the sandbox.
+ AddStaticRoute(*types.StaticRoute) error
+
+ // Remove a static route from the sandbox.
+ RemoveStaticRoute(*types.StaticRoute) error
+
+ // AddNeighbor adds a neighbor entry into the sandbox.
+ AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, force bool, option ...NeighOption) error
+
+ // DeleteNeighbor deletes neighbor entry from the sandbox.
+ DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error
+
+ // Returns an interface with methods to set neighbor options.
+ NeighborOptions() NeighborOptionSetter
+
+ // Returns an interface with methods to set interface options.
+ InterfaceOptions() IfaceOptionSetter
+
+ //Invoke
+ InvokeFunc(func()) error
+
+ // Returns an interface with methods to get sandbox state.
+ Info() Info
+
+ // Destroy the sandbox
+ Destroy() error
+
+ // restore sandbox
+ Restore(ifsopt map[string][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error
+
+ // ApplyOSTweaks applies operating system specific knobs on the sandbox
+ ApplyOSTweaks([]SandboxType)
+}
+
+// NeighborOptionSetter interface defines the option setter methods for interface options
+type NeighborOptionSetter interface {
+ // LinkName returns an option setter to set the srcName of the link that should
+ // be used in the neighbor entry
+ LinkName(string) NeighOption
+
+ // Family returns an option setter to set the address family for the neighbor
+ // entry. eg. AF_BRIDGE
+ Family(int) NeighOption
+}
+
+// IfaceOptionSetter interface defines the option setter methods for interface options.
+type IfaceOptionSetter interface {
+ // Bridge returns an option setter to set if the interface is a bridge.
+ Bridge(bool) IfaceOption
+
+ // MacAddress returns an option setter to set the MAC address.
+ MacAddress(net.HardwareAddr) IfaceOption
+
+ // Address returns an option setter to set IPv4 address.
+ Address(*net.IPNet) IfaceOption
+
+ // Address returns an option setter to set IPv6 address.
+ AddressIPv6(*net.IPNet) IfaceOption
+
+ // LinkLocalAddresses returns an option setter to set the link-local IP addresses.
+ LinkLocalAddresses([]*net.IPNet) IfaceOption
+
+ // Master returns an option setter to set the master interface if any for this
+ // interface. The master interface name should refer to the srcname of a
+ // previously added interface of type bridge.
+ Master(string) IfaceOption
+
+ // Address returns an option setter to set interface routes.
+ Routes([]*net.IPNet) IfaceOption
+}
+
+// Info represents all possible information that
+// the driver wants to place in the sandbox which includes
+// interfaces, routes and gateway
+type Info interface {
+ // The collection of Interface previously added with the AddInterface
+ // method. Note that this doesn't include network interfaces added in any
+ // other way (such as the default loopback interface which is automatically
+ // created on creation of a sandbox).
+ Interfaces() []Interface
+
+ // IPv4 gateway for the sandbox.
+ Gateway() net.IP
+
+ // IPv6 gateway for the sandbox.
+ GatewayIPv6() net.IP
+
+ // Additional static routes for the sandbox. (Note that directly
+ // connected routes are stored on the particular interface they refer to.)
+ StaticRoutes() []*types.StaticRoute
+
+ // TODO: Add ip tables etc.
+}
+
+// Interface represents the settings and identity of a network device. It is
+// used as a return type for Network.Link, and it is common practice for the
+// caller to use this information when moving interface SrcName from host
+// namespace to DstName in a different net namespace with the appropriate
+// network settings.
+type Interface interface {
+ // The name of the interface in the origin network namespace.
+ SrcName() string
+
+ // The name that will be assigned to the interface once moves inside a
+ // network namespace. When the caller passes in a DstName, it is only
+ // expected to pass a prefix. The name will modified with an appropriately
+ // auto-generated suffix.
+ DstName() string
+
+ // IPv4 address for the interface.
+ Address() *net.IPNet
+
+ // IPv6 address for the interface.
+ AddressIPv6() *net.IPNet
+
+ // LinkLocalAddresses returns the link-local IP addresses assigned to the interface.
+ LinkLocalAddresses() []*net.IPNet
+
+ // IP routes for the interface.
+ Routes() []*net.IPNet
+
+ // Bridge returns true if the interface is a bridge
+ Bridge() bool
+
+ // Master returns the srcname of the master interface for this interface.
+ Master() string
+
+ // Remove an interface from the sandbox by renaming to original name
+ // and moving it out of the sandbox.
+ Remove() error
+
+ // Statistics returns the statistics for this interface
+ Statistics() (*types.InterfaceStatistics, error)
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/sandbox_freebsd.go b/vendor/github.com/docker/libnetwork/osl/sandbox_freebsd.go
new file mode 100644
index 000000000..e5bc6278e
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/sandbox_freebsd.go
@@ -0,0 +1,44 @@
+package osl
+
+import "testing"
+
+// GenerateKey generates a sandbox key based on the passed
+// container id.
+func GenerateKey(containerID string) string {
+ maxLen := 12
+ if len(containerID) < maxLen {
+ maxLen = len(containerID)
+ }
+
+ return containerID[:maxLen]
+}
+
+// NewSandbox provides a new sandbox instance created in an os specific way
+// provided a key which uniquely identifies the sandbox
+func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
+ return nil, nil
+}
+
+// GetSandboxForExternalKey returns sandbox object for the supplied path
+func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
+ return nil, nil
+}
+
+// GC triggers garbage collection of namespace path right away
+// and waits for it.
+func GC() {
+}
+
+// InitOSContext initializes OS context while configuring network resources
+func InitOSContext() func() {
+ return func() {}
+}
+
+// SetupTestOSContext sets up a separate test OS context in which tests will be executed.
+func SetupTestOSContext(t *testing.T) func() {
+ return func() {}
+}
+
+// SetBasePath sets the base url prefix for the ns path
+func SetBasePath(path string) {
+}
diff --git a/vendor/github.com/docker/libnetwork/osl/sandbox_unsupported.go b/vendor/github.com/docker/libnetwork/osl/sandbox_unsupported.go
new file mode 100644
index 000000000..51a656c80
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/osl/sandbox_unsupported.go
@@ -0,0 +1,22 @@
+// +build !linux,!windows,!freebsd
+
+package osl
+
+import "errors"
+
+var (
+ // ErrNotImplemented is for platforms which don't implement sandbox
+ ErrNotImplemented = errors.New("not implemented")
+)
+
+// NewSandbox provides a new sandbox instance created in an os specific way
+// provided a key which uniquely identifies the sandbox
+func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
+ return nil, ErrNotImplemented
+}
+
+// GenerateKey generates a sandbox key based on the passed
+// container id.
+func GenerateKey(containerID string) string {
+ return ""
+}
diff --git a/vendor/github.com/docker/libnetwork/resolvconf/dns/resolvconf.go b/vendor/github.com/docker/libnetwork/resolvconf/dns/resolvconf.go
index 6c6dac589..e348bc57f 100644
--- a/vendor/github.com/docker/libnetwork/resolvconf/dns/resolvconf.go
+++ b/vendor/github.com/docker/libnetwork/resolvconf/dns/resolvconf.go
@@ -4,10 +4,14 @@ import (
"regexp"
)
-// IPLocalhost is a regex patter for localhost IP address range.
+// IPLocalhost is a regex pattern for IPv4 or IPv6 loopback range.
const IPLocalhost = `((127\.([0-9]{1,3}\.){2}[0-9]{1,3})|(::1)$)`
+// IPv4Localhost is a regex pattern for IPv4 localhost address range.
+const IPv4Localhost = `(127\.([0-9]{1,3}\.){2}[0-9]{1,3})`
+
var localhostIPRegexp = regexp.MustCompile(IPLocalhost)
+var localhostIPv4Regexp = regexp.MustCompile(IPv4Localhost)
// IsLocalhost returns true if ip matches the localhost IP regular expression.
// Used for determining if nameserver settings are being passed which are
@@ -15,3 +19,8 @@ var localhostIPRegexp = regexp.MustCompile(IPLocalhost)
func IsLocalhost(ip string) bool {
return localhostIPRegexp.MatchString(ip)
}
+
+// IsIPv4Localhost returns true if ip matches the IPv4 localhost regular expression.
+func IsIPv4Localhost(ip string) bool {
+ return localhostIPv4Regexp.MatchString(ip)
+}
diff --git a/vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go b/vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go
index 507d9ef50..23caf7f12 100644
--- a/vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go
+++ b/vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go
@@ -8,10 +8,15 @@ import (
"strings"
"sync"
- "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/ioutils"
- "github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/resolvconf/dns"
+ "github.com/docker/libnetwork/types"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ // DefaultResolvConf points to the default file used for dns configuration on a linux machine
+ DefaultResolvConf = "/etc/resolv.conf"
)
var (
@@ -25,7 +30,7 @@ var (
// -- e.g. other link-local types -- either won't work in containers or are unnecessary.
// For readability and sufficiency for Docker purposes this seemed more reasonable than a
// 1000+ character regexp with exact and complete IPv6 validation
- ipv6Address = `([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})`
+ ipv6Address = `([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})(%\w+)?`
localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + dns.IPLocalhost + `\s*\n*`)
nsIPv6Regexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`)
@@ -50,15 +55,7 @@ type File struct {
// Get returns the contents of /etc/resolv.conf and its hash
func Get() (*File, error) {
- resolv, err := ioutil.ReadFile("/etc/resolv.conf")
- if err != nil {
- return nil, err
- }
- hash, err := ioutils.HashData(bytes.NewReader(resolv))
- if err != nil {
- return nil, err
- }
- return &File{Content: resolv, Hash: hash}, nil
+ return GetSpecific(DefaultResolvConf)
}
// GetSpecific returns the contents of the user specified resolv.conf file and its hash
@@ -122,11 +119,11 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool) (*File, error) {
}
// if the resulting resolvConf has no more nameservers defined, add appropriate
// default DNS servers for IPv4 and (optionally) IPv6
- if len(GetNameservers(cleanedResolvConf, netutils.IP)) == 0 {
- logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers : %v", defaultIPv4Dns)
+ if len(GetNameservers(cleanedResolvConf, types.IP)) == 0 {
+ logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers: %v", defaultIPv4Dns)
dns := defaultIPv4Dns
if ipv6Enabled {
- logrus.Infof("IPv6 enabled; Adding default IPv6 external servers : %v", defaultIPv6Dns)
+ logrus.Infof("IPv6 enabled; Adding default IPv6 external servers: %v", defaultIPv6Dns)
dns = append(dns, defaultIPv6Dns...)
}
cleanedResolvConf = append(cleanedResolvConf, []byte("\n"+strings.Join(dns, "\n"))...)
@@ -158,11 +155,11 @@ func GetNameservers(resolvConf []byte, kind int) []string {
nameservers := []string{}
for _, line := range getLines(resolvConf, []byte("#")) {
var ns [][]byte
- if kind == netutils.IP {
+ if kind == types.IP {
ns = nsRegexp.FindSubmatch(line)
- } else if kind == netutils.IPv4 {
+ } else if kind == types.IPv4 {
ns = nsIPv4Regexpmatch.FindSubmatch(line)
- } else if kind == netutils.IPv6 {
+ } else if kind == types.IPv6 {
ns = nsIPv6Regexpmatch.FindSubmatch(line)
}
if len(ns) > 0 {
@@ -177,8 +174,15 @@ func GetNameservers(resolvConf []byte, kind int) []string {
// This function's output is intended for net.ParseCIDR
func GetNameserversAsCIDR(resolvConf []byte) []string {
nameservers := []string{}
- for _, nameserver := range GetNameservers(resolvConf, netutils.IP) {
- nameservers = append(nameservers, nameserver+"/32")
+ for _, nameserver := range GetNameservers(resolvConf, types.IP) {
+ var address string
+ // If IPv6, strip zone if present
+ if strings.Contains(nameserver, ":") {
+ address = strings.Split(nameserver, "%")[0] + "/128"
+ } else {
+ address = nameserver + "/32"
+ }
+ nameservers = append(nameservers, address)
}
return nameservers
}
diff --git a/vendor/github.com/docker/libnetwork/types/types.go b/vendor/github.com/docker/libnetwork/types/types.go
index 44ee563e6..b102ba4c3 100644
--- a/vendor/github.com/docker/libnetwork/types/types.go
+++ b/vendor/github.com/docker/libnetwork/types/types.go
@@ -7,12 +7,35 @@ import (
"net"
"strconv"
"strings"
+
+ "github.com/ishidawataru/sctp"
+)
+
+// constants for the IP address type
+const (
+ IP = iota // IPv4 and IPv6
+ IPv4
+ IPv6
)
+// EncryptionKey is the libnetwork representation of the key distributed by the lead
+// manager.
+type EncryptionKey struct {
+ Subsystem string
+ Algorithm int32
+ Key []byte
+ LamportTime uint64
+}
+
// UUID represents a globally unique ID of various resources like network and endpoint
type UUID string
-// TransportPort represent a local Layer 4 endpoint
+// QosPolicy represents a quality of service policy on an endpoint
+type QosPolicy struct {
+ MaxEgressBandwidth uint64
+}
+
+// TransportPort represents a local Layer 4 endpoint
type TransportPort struct {
Proto Protocol
Port uint16
@@ -58,7 +81,7 @@ func (t *TransportPort) FromString(s string) error {
return BadRequestErrorf("invalid format for transport port: %s", s)
}
-// PortBinding represent a port binding between the container and the host
+// PortBinding represents a port binding between the container and the host
type PortBinding struct {
Proto Protocol
IP net.IP
@@ -75,6 +98,8 @@ func (p PortBinding) HostAddr() (net.Addr, error) {
return &net.UDPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
case TCP:
return &net.TCPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
+ case SCTP:
+ return &sctp.SCTPAddr{IP: []net.IP{p.HostIP}, Port: int(p.HostPort)}, nil
default:
return nil, ErrInvalidProtocolBinding(p.Proto.String())
}
@@ -87,6 +112,8 @@ func (p PortBinding) ContainerAddr() (net.Addr, error) {
return &net.UDPAddr{IP: p.IP, Port: int(p.Port)}, nil
case TCP:
return &net.TCPAddr{IP: p.IP, Port: int(p.Port)}, nil
+ case SCTP:
+ return &sctp.SCTPAddr{IP: []net.IP{p.IP}, Port: int(p.Port)}, nil
default:
return nil, ErrInvalidProtocolBinding(p.Proto.String())
}
@@ -104,21 +131,26 @@ func (p *PortBinding) GetCopy() PortBinding {
}
}
-// String return the PortBinding structure in string form
+// String returns the PortBinding structure in string form
func (p *PortBinding) String() string {
ret := fmt.Sprintf("%s/", p.Proto)
if p.IP != nil {
- ret = fmt.Sprintf("%s%s", ret, p.IP.String())
+ ret += p.IP.String()
}
ret = fmt.Sprintf("%s:%d/", ret, p.Port)
if p.HostIP != nil {
- ret = fmt.Sprintf("%s%s", ret, p.HostIP.String())
+ ret += p.HostIP.String()
}
ret = fmt.Sprintf("%s:%d", ret, p.HostPort)
return ret
}
-// FromString reads the TransportPort structure from string
+// FromString reads the PortBinding structure from string s.
+// String s is a triple of "protocol/containerIP:port/hostIP:port"
+// containerIP and hostIP can be in dotted decimal ("192.0.2.1") or IPv6 ("2001:db8::68") form.
+// Zoned addresses ("169.254.0.23%eth0" or "fe80::1ff:fe23:4567:890a%eth0") are not supported.
+// If string s is incorrectly formatted or the IP addresses or ports cannot be parsed, FromString
+// returns an error.
func (p *PortBinding) FromString(s string) error {
ps := strings.Split(s, "/")
if len(ps) != 3 {
@@ -140,21 +172,19 @@ func (p *PortBinding) FromString(s string) error {
}
func parseIPPort(s string) (net.IP, uint16, error) {
- pp := strings.Split(s, ":")
- if len(pp) != 2 {
- return nil, 0, BadRequestErrorf("invalid format: %s", s)
+ hoststr, portstr, err := net.SplitHostPort(s)
+ if err != nil {
+ return nil, 0, err
}
- var ip net.IP
- if pp[0] != "" {
- if ip = net.ParseIP(pp[0]); ip == nil {
- return nil, 0, BadRequestErrorf("invalid ip: %s", pp[0])
- }
+ ip := net.ParseIP(hoststr)
+ if ip == nil {
+ return nil, 0, BadRequestErrorf("invalid ip: %s", hoststr)
}
- port, err := strconv.ParseUint(pp[1], 10, 16)
+ port, err := strconv.ParseUint(portstr, 10, 16)
if err != nil {
- return nil, 0, BadRequestErrorf("invalid port: %s", pp[1])
+ return nil, 0, BadRequestErrorf("invalid port: %s", portstr)
}
return ip, uint16(port), nil
@@ -212,9 +242,11 @@ const (
TCP = 6
// UDP is for the UDP ip protocol
UDP = 17
+ // SCTP is for the SCTP ip protocol
+ SCTP = 132
)
-// Protocol represents a IP protocol number
+// Protocol represents an IP protocol number
type Protocol uint8
func (p Protocol) String() string {
@@ -225,6 +257,8 @@ func (p Protocol) String() string {
return "tcp"
case UDP:
return "udp"
+ case SCTP:
+ return "sctp"
default:
return fmt.Sprintf("%d", p)
}
@@ -239,6 +273,8 @@ func ParseProtocol(s string) Protocol {
return UDP
case "tcp":
return TCP
+ case "sctp":
+ return SCTP
default:
return 0
}
@@ -296,6 +332,8 @@ func CompareIPNet(a, b *net.IPNet) bool {
}
// GetMinimalIP returns the address in its shortest form
+// If ip contains an IPv4-mapped IPv6 address, the 4-octet form of the IPv4 address will be returned.
+// Otherwise ip is returned unchanged.
func GetMinimalIP(ip net.IP) net.IP {
if ip != nil && ip.To4() != nil {
return ip.To4()
@@ -318,6 +356,12 @@ func GetMinimalIPNet(nw *net.IPNet) *net.IPNet {
return nw
}
+// IsIPNetValid returns true if the ipnet is a valid network/mask
+// combination. Otherwise returns false.
+func IsIPNetValid(nw *net.IPNet) bool {
+ return nw.String() != "0.0.0.0/0"
+}
+
var v4inV6MaskPrefix = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
// compareIPMask checks if the passed ip and mask are semantically compatible.
diff --git a/vendor/github.com/docker/libnetwork/vendor.conf b/vendor/github.com/docker/libnetwork/vendor.conf
new file mode 100644
index 000000000..f2bb55223
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/vendor.conf
@@ -0,0 +1,50 @@
+github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
+github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
+github.com/Microsoft/go-winio v0.4.11
+github.com/Microsoft/hcsshim v0.7.3
+github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
+github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
+github.com/codegangsta/cli a65b733b303f0055f8d324d805f393cd3e7a7904
+github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b
+github.com/coreos/etcd v3.2.1
+github.com/coreos/go-semver v0.2.0
+github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
+go.etcd.io/bbolt v1.3.1-etcd.8
+
+github.com/docker/docker 162ba6016def672690ee4a1f3978368853a1e149
+github.com/docker/go-connections 7beb39f0b969b075d1325fecb092faf27fd357b6
+github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
+github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
+github.com/docker/libkv 458977154600b9f23984d9f4b82e79570b5ae12b
+
+github.com/godbus/dbus v4.0.0
+github.com/gogo/protobuf v1.0.0
+github.com/gorilla/context v1.1
+github.com/gorilla/mux v1.1
+github.com/hashicorp/consul v0.5.2
+github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
+github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
+github.com/hashicorp/memberlist 3d8438da9589e7b608a83ffac1ef8211486bcb7c
+github.com/sean-/seed e2103e2c35297fb7e17febb81e49b312087a2372
+github.com/hashicorp/go-sockaddr 6d291a969b86c4b633730bfc6b8b9d64c3aafed9
+github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
+github.com/mattn/go-shellwords v1.0.3
+github.com/miekg/dns v1.0.7
+github.com/opencontainers/go-digest v1.0.0-rc1
+github.com/opencontainers/image-spec v1.0.1
+github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
+github.com/opencontainers/runtime-spec v1.0.1
+github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
+github.com/sirupsen/logrus v1.0.3
+github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065
+github.com/vishvananda/netlink b2de5d10e38ecce8607e6b438b6d174f389a004e
+github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
+golang.org/x/crypto 1a580b3eff7814fc9b40602fd35256c63b50f491
+golang.org/x/net 0ed95abb35c445290478a5348a7b38bb154135fd
+golang.org/x/sys 37707fdb30a5b38865cfb95e5aab41707daec7fd
+golang.org/x/sync fd80eb99c8f653c847d294a001bdf2a3a6f768f5
+github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
+github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb
+
+gotest.tools v2.1.0
+github.com/google/go-cmp v0.2.0