From bc5fac3a7cbef9c73dd3a739c830066c88fa595f Mon Sep 17 00:00:00 2001
From: Matthew Heon <matthew.heon@gmail.com>
Date: Tue, 25 Sep 2018 12:41:40 -0400
Subject: [PATCH] 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>
---
 vendor.conf                                   |   2 +-
 vendor/github.com/docker/libnetwork/README.md |  15 +-
 .../docker/libnetwork/ipamutils/utils.go      | 135 ++++
 .../docker/libnetwork/netutils/utils.go       |  11 +-
 .../libnetwork/netutils/utils_freebsd.go      |  23 +
 .../docker/libnetwork/netutils/utils_linux.go |  84 ++-
 .../libnetwork/netutils/utils_windows.go      |  25 +
 .../docker/libnetwork/ns/init_linux.go        | 140 ++++
 .../docker/libnetwork/ns/init_windows.go      |   3 +
 .../libnetwork/osl/interface_freebsd.go       |   4 +
 .../docker/libnetwork/osl/interface_linux.go  | 460 ++++++++++++
 .../libnetwork/osl/interface_windows.go       |   4 +
 .../docker/libnetwork/osl/kernel/knobs.go     |  16 +
 .../libnetwork/osl/kernel/knobs_linux.go      |  47 ++
 .../osl/kernel/knobs_unsupported.go           |   7 +
 .../docker/libnetwork/osl/namespace_linux.go  | 657 ++++++++++++++++++
 .../libnetwork/osl/namespace_unsupported.go   |  17 +
 .../libnetwork/osl/namespace_windows.go       |  38 +
 .../docker/libnetwork/osl/neigh_freebsd.go    |   4 +
 .../docker/libnetwork/osl/neigh_linux.go      | 194 ++++++
 .../docker/libnetwork/osl/neigh_windows.go    |   4 +
 .../docker/libnetwork/osl/options_linux.go    |  73 ++
 .../docker/libnetwork/osl/route_linux.go      | 203 ++++++
 .../docker/libnetwork/osl/sandbox.go          | 187 +++++
 .../docker/libnetwork/osl/sandbox_freebsd.go  |  44 ++
 .../libnetwork/osl/sandbox_unsupported.go     |  22 +
 .../libnetwork/resolvconf/dns/resolvconf.go   |  11 +-
 .../libnetwork/resolvconf/resolvconf.go       |  44 +-
 .../docker/libnetwork/types/types.go          |  86 ++-
 .../github.com/docker/libnetwork/vendor.conf  |  50 ++
 30 files changed, 2552 insertions(+), 58 deletions(-)
 create mode 100644 vendor/github.com/docker/libnetwork/ipamutils/utils.go
 create mode 100644 vendor/github.com/docker/libnetwork/netutils/utils_freebsd.go
 create mode 100644 vendor/github.com/docker/libnetwork/netutils/utils_windows.go
 create mode 100644 vendor/github.com/docker/libnetwork/ns/init_linux.go
 create mode 100644 vendor/github.com/docker/libnetwork/ns/init_windows.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/interface_freebsd.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/interface_linux.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/interface_windows.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/kernel/knobs.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/kernel/knobs_linux.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/kernel/knobs_unsupported.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/namespace_linux.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/namespace_unsupported.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/namespace_windows.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/neigh_freebsd.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/neigh_linux.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/neigh_windows.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/options_linux.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/route_linux.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/sandbox.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/sandbox_freebsd.go
 create mode 100644 vendor/github.com/docker/libnetwork/osl/sandbox_unsupported.go
 create mode 100644 vendor/github.com/docker/libnetwork/vendor.conf

diff --git a/vendor.conf b/vendor.conf
index 48f1277734..d613dceb2e 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 3f10a0311c..a9020381ab 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 0000000000..3fd37cd884
--- /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 482e4f038f..7de98f6b07 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 0000000000..02bcd32aa8
--- /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 782e542a52..10a5e109ee 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 0000000000..73af44ec71
--- /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 0000000000..567a6242ac
--- /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 0000000000..f5838f81dd
--- /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 0000000000..9c0141fd9b
--- /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 0000000000..4f8ff3d639
--- /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 0000000000..9c0141fd9b
--- /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 0000000000..a7cd7dbb72
--- /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 0000000000..964280650c
--- /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 0000000000..32f258f416
--- /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 0000000000..abb748b567
--- /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 0000000000..74372e2492
--- /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 0000000000..49503c00ff
--- /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 0000000000..280f006396
--- /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 0000000000..6bf1c16dc5
--- /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 0000000000..280f006396
--- /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 0000000000..818669647f
--- /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 0000000000..a9ff191b37
--- /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 0000000000..5019e068df
--- /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 0000000000..e5bc6278ee
--- /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 0000000000..51a656c806
--- /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 6c6dac589f..e348bc57f5 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 507d9ef50d..23caf7f120 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 44ee563e69..b102ba4c39 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)
-	}
-
-	var ip net.IP
-	if pp[0] != "" {
-		if ip = net.ParseIP(pp[0]); ip == nil {
-			return nil, 0, BadRequestErrorf("invalid ip: %s", pp[0])
-		}
-	}
-
-	port, err := strconv.ParseUint(pp[1], 10, 16)
+	hoststr, portstr, err := net.SplitHostPort(s)
 	if err != nil {
-		return nil, 0, BadRequestErrorf("invalid port: %s", pp[1])
+		return nil, 0, err
+	}
+
+	ip := net.ParseIP(hoststr)
+	if ip == nil {
+		return nil, 0, BadRequestErrorf("invalid ip: %s", hoststr)
+	}
+
+	port, err := strconv.ParseUint(portstr, 10, 16)
+	if err != nil {
+		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 0000000000..f2bb55223e
--- /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