diff --git a/vendor.conf b/vendor.conf index 8992f6cf7d..a1d4ead656 100644 --- a/vendor.conf +++ b/vendor.conf @@ -23,7 +23,7 @@ github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 github.com/imdario/mergo 0.2.1 #get libnetwork packages -github.com/docker/libnetwork 382be38ce860738d80b53d7875d83abd5970d9d6 https://github.com/aaronlehmann/libnetwork +github.com/docker/libnetwork e8431956af5df6816e232d68376c012c2617edbd github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec diff --git a/vendor/github.com/docker/libnetwork/bitseq/sequence.go b/vendor/github.com/docker/libnetwork/bitseq/sequence.go index a67999313c..86cf69b34f 100644 --- a/vendor/github.com/docker/libnetwork/bitseq/sequence.go +++ b/vendor/github.com/docker/libnetwork/bitseq/sequence.go @@ -6,6 +6,7 @@ package bitseq import ( "encoding/binary" "encoding/json" + "errors" "fmt" "sync" @@ -26,9 +27,9 @@ const ( var ( // ErrNoBitAvailable is returned when no more bits are available to set - ErrNoBitAvailable = fmt.Errorf("no bit available") + ErrNoBitAvailable = errors.New("no bit available") // ErrBitAllocated is returned when the specific bit requested is already set - ErrBitAllocated = fmt.Errorf("requested bit is already allocated") + ErrBitAllocated = errors.New("requested bit is already allocated") ) // Handle contains the sequece representing the bitmask and its identifier @@ -373,7 +374,7 @@ func (h *Handle) validateOrdinal(ordinal uint64) error { h.Lock() defer h.Unlock() if ordinal >= h.bits { - return fmt.Errorf("bit does not belong to the sequence") + return errors.New("bit does not belong to the sequence") } return nil } @@ -418,7 +419,7 @@ func (h *Handle) ToByteArray() ([]byte, error) { // FromByteArray reads his handle's data from a byte array func (h *Handle) FromByteArray(ba []byte) error { if ba == nil { - return fmt.Errorf("nil byte array") + return errors.New("nil byte array") } nh := &sequence{} diff --git a/vendor/github.com/docker/libnetwork/controller.go b/vendor/github.com/docker/libnetwork/controller.go index e7942490b7..24d71e4325 100644 --- a/vendor/github.com/docker/libnetwork/controller.go +++ b/vendor/github.com/docker/libnetwork/controller.go @@ -273,7 +273,7 @@ func (c *controller) SetKeys(keys []*types.EncryptionKey) error { } for s, count := range subsysKeys { if count != keyringSize { - return fmt.Errorf("incorrect number of keys for susbsystem %v", s) + return fmt.Errorf("incorrect number of keys for subsystem %v", s) } } @@ -582,7 +582,7 @@ func (c *controller) pushNodeDiscovery(d driverapi.Driver, cap driverapi.Capabil err = d.DiscoverDelete(discoverapi.NodeDiscovery, nodeData) } if err != nil { - logrus.Debugf("discovery notification error : %v", err) + logrus.Debugf("discovery notification error: %v", err) } } } @@ -932,6 +932,7 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (s populatedEndpoints: map[string]struct{}{}, config: containerConfig{}, controller: c, + extDNS: []extDNSEntry{}, } } sBox = sb @@ -997,7 +998,7 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (s err = sb.storeUpdate() if err != nil { - return nil, fmt.Errorf("updating the store state of sandbox failed: %v", err) + return nil, fmt.Errorf("failed to update the store state of sandbox: %v", err) } return sb, nil diff --git a/vendor/github.com/docker/libnetwork/datastore/cache.go b/vendor/github.com/docker/libnetwork/datastore/cache.go index 97b6009113..49839ae8f2 100644 --- a/vendor/github.com/docker/libnetwork/datastore/cache.go +++ b/vendor/github.com/docker/libnetwork/datastore/cache.go @@ -1,6 +1,7 @@ package datastore import ( + "errors" "fmt" "sync" @@ -36,7 +37,7 @@ func (c *cache) kmap(kvObject KVObject) (kvMap, error) { // Bail out right away if the kvObject does not implement KVConstructor ctor, ok := kvObject.(KVConstructor) if !ok { - return nil, fmt.Errorf("error while populating kmap, object does not implement KVConstructor interface") + return nil, errors.New("error while populating kmap, object does not implement KVConstructor interface") } kvList, err := c.ds.store.List(keyPrefix) @@ -153,7 +154,7 @@ func (c *cache) get(key string, kvObject KVObject) error { ctor, ok := o.(KVConstructor) if !ok { - return fmt.Errorf("kvobject does not implement KVConstructor interface. could not get object") + return errors.New("kvobject does not implement KVConstructor interface. could not get object") } return ctor.CopyTo(kvObject) diff --git a/vendor/github.com/docker/libnetwork/driverapi/driverapi.go b/vendor/github.com/docker/libnetwork/driverapi/driverapi.go index 6e66ea221e..7fe6f611a4 100644 --- a/vendor/github.com/docker/libnetwork/driverapi/driverapi.go +++ b/vendor/github.com/docker/libnetwork/driverapi/driverapi.go @@ -62,7 +62,7 @@ type Driver interface { // programming to allow the external connectivity dictated by the passed options ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error - // RevokeExternalConnectivity aks the driver to remove any external connectivity + // RevokeExternalConnectivity asks the driver to remove any external connectivity // programming that was done so far RevokeExternalConnectivity(nid, eid string) error @@ -72,7 +72,7 @@ type Driver interface { // only invoked for the global scope driver. EventNotify(event EventType, nid string, tableName string, key string, value []byte) - // Type returns the the type of this driver, the network type this driver manages + // Type returns the type of this driver, the network type this driver manages Type() string // IsBuiltIn returns true if it is a built-in driver diff --git a/vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go b/vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go index ec999731cd..fa051bde5a 100644 --- a/vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -186,24 +186,24 @@ func (c *networkConfiguration) Validate() error { // Conflicts check if two NetworkConfiguration objects overlap func (c *networkConfiguration) Conflicts(o *networkConfiguration) error { if o == nil { - return fmt.Errorf("same configuration") + return errors.New("same configuration") } // Also empty, because only one network with empty name is allowed if c.BridgeName == o.BridgeName { - return fmt.Errorf("networks have same bridge name") + return errors.New("networks have same bridge name") } // They must be in different subnets if (c.AddressIPv4 != nil && o.AddressIPv4 != nil) && (c.AddressIPv4.Contains(o.AddressIPv4.IP) || o.AddressIPv4.Contains(c.AddressIPv4.IP)) { - return fmt.Errorf("networks have overlapping IPv4") + return errors.New("networks have overlapping IPv4") } // They must be in different v6 subnets if (c.AddressIPv6 != nil && o.AddressIPv6 != nil) && (c.AddressIPv6.Contains(o.AddressIPv6.IP) || o.AddressIPv6.Contains(c.AddressIPv6.IP)) { - return fmt.Errorf("networks have overlapping IPv6") + return errors.New("networks have overlapping IPv6") } return nil diff --git a/vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering.go b/vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering.go index aa6c8eba4c..884c7115ec 100644 --- a/vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering.go +++ b/vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering.go @@ -1,6 +1,7 @@ package bridge import ( + "errors" "fmt" "io/ioutil" "os" @@ -37,7 +38,7 @@ func setupBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) e logrus.Warnf("running inside docker container, ignoring missing kernel params: %v", err) err = nil } else { - err = fmt.Errorf("please ensure that br_netfilter kernel module is loaded") + err = errors.New("please ensure that br_netfilter kernel module is loaded") } } } diff --git a/vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go b/vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go index 9df4cdc6c6..0d4d549004 100644 --- a/vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go +++ b/vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go @@ -1,6 +1,7 @@ package bridge import ( + "errors" "fmt" "net" @@ -17,7 +18,7 @@ const ( func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) { // Sanity check. if config.EnableIPTables == false { - return nil, nil, nil, fmt.Errorf("cannot create new chains, EnableIPTable is disabled") + return nil, nil, nil, errors.New("cannot create new chains, EnableIPTable is disabled") } hairpinMode := !config.EnableUserlandProxy @@ -68,7 +69,7 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt // Sanity check. if driverConfig.EnableIPTables == false { - return fmt.Errorf("Cannot program chains, EnableIPTable is disabled") + return errors.New("Cannot program chains, EnableIPTable is disabled") } // Pickup this configuration option from driver diff --git a/vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go b/vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go index 772b40eed3..7f8707266d 100644 --- a/vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go +++ b/vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go @@ -1,6 +1,7 @@ package bridge import ( + "errors" "fmt" "io/ioutil" "net" @@ -13,7 +14,7 @@ import ( func selectIPv4Address(addresses []netlink.Addr, selector *net.IPNet) (netlink.Addr, error) { if len(addresses) == 0 { - return netlink.Addr{}, fmt.Errorf("unable to select an address as the address pool is empty") + return netlink.Addr{}, errors.New("unable to select an address as the address pool is empty") } if selector != nil { for _, addr := range addresses { diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go b/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go index 703d13f9a5..122c3f6b1b 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go @@ -402,7 +402,7 @@ func (n *network) getBridgeNamePrefix(s *subnet) string { return "ov-" + fmt.Sprintf("%06x", n.vxlanID(s)) } -func isOverlap(nw *net.IPNet) bool { +func checkOverlap(nw *net.IPNet) error { var nameservers []string if rc, err := resolvconf.Get(); err == nil { @@ -410,14 +410,14 @@ func isOverlap(nw *net.IPNet) bool { } if err := netutils.CheckNameserverOverlaps(nameservers, nw); err != nil { - return true + return fmt.Errorf("overlay subnet %s failed check with nameserver: %v: %v", nw.String(), nameservers, err) } if err := netutils.CheckRouteOverlaps(nw); err != nil { - return true + return fmt.Errorf("overlay subnet %s failed check with host route table: %v", nw.String(), err) } - return false + return nil } func (n *network) restoreSubnetSandbox(s *subnet, brName, vxlanName string) error { @@ -456,8 +456,8 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error // Try to delete the vxlan interface by vni if already present deleteVxlanByVNI("", n.vxlanID(s)) - if isOverlap(s.subnetIP) { - return fmt.Errorf("overlay subnet %s has conflicts in the host while running in host mode", s.subnetIP.String()) + if err := checkOverlap(s.subnetIP); err != nil { + return err } } diff --git a/vendor/github.com/docker/libnetwork/drivers/remote/driver.go b/vendor/github.com/docker/libnetwork/drivers/remote/driver.go index f35a941f09..12dbc121ce 100644 --- a/vendor/github.com/docker/libnetwork/drivers/remote/driver.go +++ b/vendor/github.com/docker/libnetwork/drivers/remote/driver.go @@ -1,6 +1,7 @@ package remote import ( + "errors" "fmt" "net" @@ -132,7 +133,7 @@ func (d *driver) DeleteNetwork(nid string) error { func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { if ifInfo == nil { - return fmt.Errorf("must not be called with nil InterfaceInfo") + return errors.New("must not be called with nil InterfaceInfo") } reqIface := &api.EndpointInterface{} diff --git a/vendor/github.com/docker/libnetwork/drivers/windows/overlay/peerdb_windows.go b/vendor/github.com/docker/libnetwork/drivers/windows/overlay/peerdb_windows.go index 47f4bfbcc4..20f190f86e 100644 --- a/vendor/github.com/docker/libnetwork/drivers/windows/overlay/peerdb_windows.go +++ b/vendor/github.com/docker/libnetwork/drivers/windows/overlay/peerdb_windows.go @@ -81,7 +81,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, return err } - // Temp: We have to create a endpoint object to keep track of the HNS ID for + // Temp: We have to create an endpoint object to keep track of the HNS ID for // this endpoint so that we can retrieve it later when the endpoint is deleted. // This seems unnecessary when we already have dockers EID. See if we can pass // the global EID to HNS to use as it's ID, rather than having each HNS assign diff --git a/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go b/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go index a1cf88fc03..b3fe9bafcf 100644 --- a/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go +++ b/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go @@ -1,6 +1,7 @@ package drvregistry import ( + "errors" "fmt" "strings" "sync" @@ -160,7 +161,7 @@ func (r *DrvRegistry) GetPluginGetter() plugingetter.PluginGetter { // RegisterDriver registers the network driver when it gets discovered. func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capability driverapi.Capability) error { if strings.TrimSpace(ntype) == "" { - return fmt.Errorf("network type string cannot be empty") + return errors.New("network type string cannot be empty") } r.Lock() @@ -188,7 +189,7 @@ func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capa func (r *DrvRegistry) registerIpamDriver(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error { if strings.TrimSpace(name) == "" { - return fmt.Errorf("ipam driver name string cannot be empty") + return errors.New("ipam driver name string cannot be empty") } r.Lock() diff --git a/vendor/github.com/docker/libnetwork/idm/idm.go b/vendor/github.com/docker/libnetwork/idm/idm.go index 20be113c83..7e449a0dc8 100644 --- a/vendor/github.com/docker/libnetwork/idm/idm.go +++ b/vendor/github.com/docker/libnetwork/idm/idm.go @@ -2,6 +2,7 @@ package idm import ( + "errors" "fmt" "github.com/docker/libnetwork/bitseq" @@ -18,7 +19,7 @@ type Idm struct { // New returns an instance of id manager for a [start,end] set of numerical ids func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) { if id == "" { - return nil, fmt.Errorf("Invalid id") + return nil, errors.New("Invalid id") } if end <= start { return nil, fmt.Errorf("Invalid set range: [%d, %d]", start, end) @@ -35,7 +36,7 @@ func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) { // GetID returns the first available id in the set func (i *Idm) GetID() (uint64, error) { if i.handle == nil { - return 0, fmt.Errorf("ID set is not initialized") + return 0, errors.New("ID set is not initialized") } ordinal, err := i.handle.SetAny() return i.start + ordinal, err @@ -44,11 +45,11 @@ func (i *Idm) GetID() (uint64, error) { // GetSpecificID tries to reserve the specified id func (i *Idm) GetSpecificID(id uint64) error { if i.handle == nil { - return fmt.Errorf("ID set is not initialized") + return errors.New("ID set is not initialized") } if id < i.start || id > i.end { - return fmt.Errorf("Requested id does not belong to the set") + return errors.New("Requested id does not belong to the set") } return i.handle.Set(id - i.start) @@ -57,11 +58,11 @@ func (i *Idm) GetSpecificID(id uint64) error { // GetIDInRange returns the first available id in the set within a [start,end] range func (i *Idm) GetIDInRange(start, end uint64) (uint64, error) { if i.handle == nil { - return 0, fmt.Errorf("ID set is not initialized") + return 0, errors.New("ID set is not initialized") } if start < i.start || end > i.end { - return 0, fmt.Errorf("Requested range does not belong to the set") + return 0, errors.New("Requested range does not belong to the set") } ordinal, err := i.handle.SetAnyInRange(start-i.start, end-i.start) diff --git a/vendor/github.com/docker/libnetwork/ipams/builtin/builtin_unix.go b/vendor/github.com/docker/libnetwork/ipams/builtin/builtin_unix.go index 5baf515534..321448a344 100644 --- a/vendor/github.com/docker/libnetwork/ipams/builtin/builtin_unix.go +++ b/vendor/github.com/docker/libnetwork/ipams/builtin/builtin_unix.go @@ -3,7 +3,7 @@ package builtin import ( - "fmt" + "errors" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/ipam" @@ -20,13 +20,13 @@ func Init(ic ipamapi.Callback, l, g interface{}) error { if l != nil { if localDs, ok = l.(datastore.DataStore); !ok { - return fmt.Errorf("incorrect local datastore passed to built-in ipam init") + return errors.New("incorrect local datastore passed to built-in ipam init") } } if g != nil { if globalDs, ok = g.(datastore.DataStore); !ok { - return fmt.Errorf("incorrect global datastore passed to built-in ipam init") + return errors.New("incorrect global datastore passed to built-in ipam init") } } diff --git a/vendor/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go b/vendor/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go index 155c046875..7805e6a1d7 100644 --- a/vendor/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go +++ b/vendor/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go @@ -3,7 +3,7 @@ package builtin import ( - "fmt" + "errors" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/ipam" @@ -22,13 +22,13 @@ func InitDockerDefault(ic ipamapi.Callback, l, g interface{}) error { if l != nil { if localDs, ok = l.(datastore.DataStore); !ok { - return fmt.Errorf("incorrect local datastore passed to built-in ipam init") + return errors.New("incorrect local datastore passed to built-in ipam init") } } if g != nil { if globalDs, ok = g.(datastore.DataStore); !ok { - return fmt.Errorf("incorrect global datastore passed to built-in ipam init") + return errors.New("incorrect global datastore passed to built-in ipam init") } } diff --git a/vendor/github.com/docker/libnetwork/iptables/iptables.go b/vendor/github.com/docker/libnetwork/iptables/iptables.go index e3a41b5564..d4f4aa23dd 100644 --- a/vendor/github.com/docker/libnetwork/iptables/iptables.go +++ b/vendor/github.com/docker/libnetwork/iptables/iptables.go @@ -131,7 +131,7 @@ func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) { // ProgramChain is used to add rules to a chain func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error { if c.Name == "" { - return fmt.Errorf("Could not program chain, missing chain name") + return errors.New("Could not program chain, missing chain name") } switch c.Table { diff --git a/vendor/github.com/docker/libnetwork/netutils/utils.go b/vendor/github.com/docker/libnetwork/netutils/utils.go index 65449d3dee..7de98f6b07 100644 --- a/vendor/github.com/docker/libnetwork/netutils/utils.go +++ b/vendor/github.com/docker/libnetwork/netutils/utils.go @@ -173,7 +173,7 @@ func ReverseIP(IP string) string { // 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/network.go b/vendor/github.com/docker/libnetwork/network.go index 79e7e49a95..1b387fca55 100644 --- a/vendor/github.com/docker/libnetwork/network.go +++ b/vendor/github.com/docker/libnetwork/network.go @@ -80,10 +80,18 @@ type NetworkInfo interface { // When the function returns true, the walk will stop. type EndpointWalker func(ep Endpoint) bool +// ipInfo is the reverse mapping from IP to service name to serve the PTR query. +// extResolver is set if an externl server resolves a service name to this IP. +// Its an indication to defer PTR queries also to that external server. +type ipInfo struct { + name string + extResolver bool +} + type svcInfo struct { svcMap map[string][]net.IP svcIPv6Map map[string][]net.IP - ipMap map[string]string + ipMap map[string]*ipInfo service map[string][]servicePorts } @@ -877,7 +885,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi } if _, err = n.EndpointByName(name); err == nil { - return nil, types.ForbiddenErrorf("service endpoint with name %s already exists", name) + return nil, types.ForbiddenErrorf("endpoint with name %s already exists in network %s", name, n.Name()) } ep := &endpoint{name: name, generic: make(map[string]interface{}), iface: &endpointInterface{}} @@ -1070,10 +1078,12 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool } } -func addIPToName(ipMap map[string]string, name string, ip net.IP) { +func addIPToName(ipMap map[string]*ipInfo, name string, ip net.IP) { reverseIP := netutils.ReverseIP(ip.String()) if _, ok := ipMap[reverseIP]; !ok { - ipMap[reverseIP] = name + ipMap[reverseIP] = &ipInfo{ + name: name, + } } } @@ -1117,7 +1127,7 @@ func (n *network) addSvcRecords(name string, epIP net.IP, epIPv6 net.IP, ipMapUp sr = svcInfo{ svcMap: make(map[string][]net.IP), svcIPv6Map: make(map[string][]net.IP), - ipMap: make(map[string]string), + ipMap: make(map[string]*ipInfo), } c.svcRecords[n.ID()] = sr } @@ -1612,8 +1622,8 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) { c := n.getController() c.Lock() + defer c.Unlock() sr, ok := c.svcRecords[n.ID()] - c.Unlock() if !ok { return nil, false @@ -1621,7 +1631,6 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) { req = strings.TrimSuffix(req, ".") var ip []net.IP - n.Lock() ip, ok = sr.svcMap[req] if ipType == types.IPv6 { @@ -1634,22 +1643,38 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) { } ip = sr.svcIPv6Map[req] } - n.Unlock() if ip != nil { - return ip, false + ipLocal := make([]net.IP, len(ip)) + copy(ipLocal, ip) + return ipLocal, false } return nil, ipv6Miss } -func (n *network) ResolveIP(ip string) string { - var svc string - +func (n *network) HandleQueryResp(name string, ip net.IP) { c := n.getController() c.Lock() + defer c.Unlock() + sr, ok := c.svcRecords[n.ID()] + + if !ok { + return + } + + ipStr := netutils.ReverseIP(ip.String()) + + if ipInfo, ok := sr.ipMap[ipStr]; ok { + ipInfo.extResolver = true + } +} + +func (n *network) ResolveIP(ip string) string { + c := n.getController() + c.Lock() + defer c.Unlock() sr, ok := c.svcRecords[n.ID()] - c.Unlock() if !ok { return "" @@ -1657,15 +1682,13 @@ func (n *network) ResolveIP(ip string) string { nwName := n.Name() - n.Lock() - defer n.Unlock() - svc, ok = sr.ipMap[ip] + ipInfo, ok := sr.ipMap[ip] - if ok { - return svc + "." + nwName + if !ok || ipInfo.extResolver { + return "" } - return svc + return ipInfo.name + "." + nwName } func (n *network) ResolveService(name string) ([]*net.SRV, []net.IP) { @@ -1689,8 +1712,8 @@ func (n *network) ResolveService(name string) ([]*net.SRV, []net.IP) { svcName := strings.Join(parts[2:], ".") c.Lock() + defer c.Unlock() sr, ok := c.svcRecords[n.ID()] - c.Unlock() if !ok { return nil, nil diff --git a/vendor/github.com/docker/libnetwork/networkdb/broadcast.go b/vendor/github.com/docker/libnetwork/networkdb/broadcast.go index faaf642948..a9330cb3a2 100644 --- a/vendor/github.com/docker/libnetwork/networkdb/broadcast.go +++ b/vendor/github.com/docker/libnetwork/networkdb/broadcast.go @@ -1,7 +1,7 @@ package networkdb import ( - "fmt" + "errors" "time" "github.com/hashicorp/memberlist" @@ -90,7 +90,7 @@ func (nDB *NetworkDB) sendNodeEvent(event NodeEvent_Type) error { select { case <-notifyCh: case <-time.After(broadcastTimeout): - return fmt.Errorf("timed out broadcasting node event") + return errors.New("timed out broadcasting node event") } return nil diff --git a/vendor/github.com/docker/libnetwork/osl/interface_linux.go b/vendor/github.com/docker/libnetwork/osl/interface_linux.go index 2be99d72ea..d76966200a 100644 --- a/vendor/github.com/docker/libnetwork/osl/interface_linux.go +++ b/vendor/github.com/docker/libnetwork/osl/interface_linux.go @@ -179,6 +179,8 @@ func (i *nwIface) Remove() error { } n.Unlock() + n.checkLoV6() + return nil } @@ -318,6 +320,8 @@ func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...If n.iFaces = append(n.iFaces, i) n.Unlock() + n.checkLoV6() + return nil } @@ -378,6 +382,9 @@ func setInterfaceIPv6(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error 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) } diff --git a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go index fe8065a31e..b714ccf9fa 100644 --- a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go +++ b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go @@ -24,6 +24,10 @@ import ( const defaultPrefix = "/var/run/docker" +func init() { + reexec.Register("set-ipv6", reexecSetIPv6) +} + var ( once sync.Once garbagePathMap = make(map[string]bool) @@ -47,6 +51,7 @@ type networkNamespace struct { nextIfIndex int isDefault bool nlHandle *netlink.Handle + loV6Enabled bool sync.Mutex } @@ -216,6 +221,12 @@ func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) { 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 @@ -263,6 +274,12 @@ func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) { 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 @@ -508,3 +525,84 @@ func (n *networkNamespace) Restore(ifsopt map[string][]IfaceOption, routes []*ty 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 = 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 +} 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/resolver.go b/vendor/github.com/docker/libnetwork/resolver.go index ca3850c58e..c11aa58ed4 100644 --- a/vendor/github.com/docker/libnetwork/resolver.go +++ b/vendor/github.com/docker/libnetwork/resolver.go @@ -29,7 +29,7 @@ type Resolver interface { NameServer() string // SetExtServers configures the external nameservers the resolver // should use to forward queries - SetExtServers([]string) + SetExtServers([]extDNSEntry) // ResolverOptions returns resolv.conf options that should be set ResolverOptions() []string } @@ -54,6 +54,9 @@ type DNSBackend interface { ExecFunc(f func()) error //NdotsSet queries the backends ndots dns option settings NdotsSet() bool + // HandleQueryResp passes the name & IP from a response to the backend. backend + // can use it to maintain any required state about the resolution + HandleQueryResp(name string, ip net.IP) } const ( @@ -69,7 +72,8 @@ const ( ) type extDNSEntry struct { - ipStr string + ipStr string + hostLoopback bool } // resolver implements the Resolver interface @@ -182,13 +186,13 @@ func (r *resolver) Stop() { r.queryLock = sync.Mutex{} } -func (r *resolver) SetExtServers(dns []string) { - l := len(dns) +func (r *resolver) SetExtServers(extDNS []extDNSEntry) { + l := len(extDNS) if l > maxExtDNS { l = maxExtDNS } for i := 0; i < l; i++ { - r.extDNSList[i].ipStr = dns[i] + r.extDNSList[i] = extDNS[i] } } @@ -417,10 +421,14 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) { extConn, err = net.DialTimeout(proto, addr, extIOTimeout) } - execErr := r.backend.ExecFunc(extConnect) - if execErr != nil { - logrus.Warn(execErr) - continue + if extDNS.hostLoopback { + extConnect() + } else { + execErr := r.backend.ExecFunc(extConnect) + if execErr != nil { + logrus.Warn(execErr) + continue + } } if err != nil { logrus.Warnf("Connect failed: %s", err) @@ -462,9 +470,20 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) { logrus.Debugf("Read from DNS server failed, %s", err) continue } - r.forwardQueryEnd() - + if resp != nil { + for _, rr := range resp.Answer { + h := rr.Header() + switch h.Rrtype { + case dns.TypeA: + ip := rr.(*dns.A).A + r.backend.HandleQueryResp(h.Name, ip) + case dns.TypeAAAA: + ip := rr.(*dns.AAAA).AAAA + r.backend.HandleQueryResp(h.Name, ip) + } + } + } resp.Compress = true break } diff --git a/vendor/github.com/docker/libnetwork/sandbox.go b/vendor/github.com/docker/libnetwork/sandbox.go index 1fd585cd28..a2811af62e 100644 --- a/vendor/github.com/docker/libnetwork/sandbox.go +++ b/vendor/github.com/docker/libnetwork/sandbox.go @@ -45,7 +45,7 @@ type Sandbox interface { // EnableService makes a managed container's service available by adding the // endpoint to the service load balancer and service discovery EnableService() error - // DisableService removes a managed contianer's endpoints from the load balancer + // DisableService removes a managed container's endpoints from the load balancer // and service discovery DisableService() error } @@ -69,7 +69,7 @@ type sandbox struct { id string containerID string config containerConfig - extDNS []string + extDNS []extDNSEntry osSbox osl.Sandbox controller *controller resolver Resolver @@ -411,6 +411,13 @@ func (sb *sandbox) updateGateway(ep *endpoint) error { return nil } +func (sb *sandbox) HandleQueryResp(name string, ip net.IP) { + for _, ep := range sb.getConnectedEndpoints() { + n := ep.getNetwork() + n.HandleQueryResp(name, ip) + } +} + func (sb *sandbox) ResolveIP(ip string) string { var svc string logrus.Debugf("IP To resolve %v", ip) @@ -1167,6 +1174,17 @@ func (eh epHeap) Less(i, j int) bool { return true } + if epi.joinInfo != nil && epj.joinInfo != nil { + if (epi.joinInfo.gw != nil && epi.joinInfo.gw6 != nil) && + (epj.joinInfo.gw == nil || epj.joinInfo.gw6 == nil) { + return true + } + if (epj.joinInfo.gw != nil && epj.joinInfo.gw6 != nil) && + (epi.joinInfo.gw == nil || epi.joinInfo.gw6 == nil) { + return false + } + } + if ci != nil { cip, ok = ci.epPriority[eh[i].ID()] if !ok { diff --git a/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go b/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go index f4d1fad605..464793d71f 100644 --- a/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go +++ b/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go @@ -14,6 +14,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/etchosts" "github.com/docker/libnetwork/resolvconf" + "github.com/docker/libnetwork/resolvconf/dns" "github.com/docker/libnetwork/types" ) @@ -100,8 +101,6 @@ func (sb *sandbox) buildHostsFile() error { } func (sb *sandbox) updateHostsFile(ifaceIP string) error { - var mhost string - if ifaceIP == "" { return nil } @@ -110,11 +109,17 @@ func (sb *sandbox) updateHostsFile(ifaceIP string) error { return nil } + // User might have provided a FQDN in hostname or split it across hostname + // and domainname. We want the FQDN and the bare hostname. + fqdn := sb.config.hostName + mhost := sb.config.hostName if sb.config.domainName != "" { - mhost = fmt.Sprintf("%s.%s %s", sb.config.hostName, sb.config.domainName, - sb.config.hostName) - } else { - mhost = sb.config.hostName + fqdn = fmt.Sprintf("%s.%s", fqdn, sb.config.domainName) + } + + parts := strings.SplitN(fqdn, ".", 2) + if len(parts) == 2 { + mhost = fmt.Sprintf("%s %s", fqdn, parts[0]) } extraContent := []etchosts.Record{{Hosts: mhost, IP: ifaceIP}} @@ -161,6 +166,20 @@ func (sb *sandbox) restorePath() { } } +func (sb *sandbox) setExternalResolvers(content []byte, addrType int, checkLoopback bool) { + servers := resolvconf.GetNameservers(content, addrType) + for _, ip := range servers { + hostLoopback := false + if checkLoopback { + hostLoopback = dns.IsIPv4Localhost(ip) + } + sb.extDNS = append(sb.extDNS, extDNSEntry{ + ipStr: ip, + hostLoopback: hostLoopback, + }) + } +} + func (sb *sandbox) setupDNS() error { var newRC *resolvconf.File @@ -208,7 +227,17 @@ func (sb *sandbox) setupDNS() error { if err != nil { return err } + // After building the resolv.conf from the user config save the + // external resolvers in the sandbox. Note that --dns 127.0.0.x + // config refers to the loopback in the container namespace + sb.setExternalResolvers(newRC.Content, types.IPv4, false) } else { + // If the host resolv.conf file has 127.0.0.x container should + // use the host restolver for queries. This is supported by the + // docker embedded DNS server. Hence save the external resolvers + // before filtering it out. + sb.setExternalResolvers(currRC.Content, types.IPv4, true) + // Replace any localhost/127.* (at this point we have no info about ipv6, pass it as true) if newRC, err = resolvconf.FilterResolvDNS(currRC.Content, true); err != nil { return err @@ -297,7 +326,6 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error { // Embedded DNS server has to be enabled for this sandbox. Rebuild the container's // resolv.conf by doing the following -// - Save the external name servers in resolv.conf in the sandbox // - Add only the embedded server's IP to container's resolv.conf // - If the embedded server needs any resolv.conf options add it to the current list func (sb *sandbox) rebuildDNS() error { @@ -306,10 +334,9 @@ func (sb *sandbox) rebuildDNS() error { return err } - // localhost entries have already been filtered out from the list - // retain only the v4 servers in sb for forwarding the DNS queries - sb.extDNS = resolvconf.GetNameservers(currRC.Content, types.IPv4) - + if len(sb.extDNS) == 0 { + sb.setExternalResolvers(currRC.Content, types.IPv4, false) + } var ( dnsList = []string{sb.resolver.NameServer()} dnsOptionsList = resolvconf.GetOptions(currRC.Content) diff --git a/vendor/github.com/docker/libnetwork/sandbox_store.go b/vendor/github.com/docker/libnetwork/sandbox_store.go index 8b36d688a1..d50163ded5 100644 --- a/vendor/github.com/docker/libnetwork/sandbox_store.go +++ b/vendor/github.com/docker/libnetwork/sandbox_store.go @@ -27,7 +27,7 @@ type sbState struct { dbExists bool Eps []epState EpPriority map[string]int - ExtDNS []string + ExtDNS []extDNSEntry } func (sbs *sbState) Key() []string {