From fbdb3c3a4b15720c0df3a59d4bef0773b365c2b1 Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Tue, 22 Mar 2016 12:30:39 -0700 Subject: [PATCH] Vendoring libnetwork v0.7.0-dev.10 Signed-off-by: Alessandro Boch --- hack/vendor.sh | 2 +- .../docker_cli_network_unix_test.go | 6 +- .../github.com/docker/libnetwork/CHANGELOG.md | 5 + .../github.com/docker/libnetwork/network.go | 107 ++++++++++++------ .../github.com/docker/libnetwork/resolver.go | 48 +++++--- .../github.com/docker/libnetwork/sandbox.go | 53 ++++++--- 6 files changed, 155 insertions(+), 66 deletions(-) diff --git a/hack/vendor.sh b/hack/vendor.sh index f619d7766f..6fbc76aa82 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -29,7 +29,7 @@ clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837 clone git github.com/imdario/mergo 0.2.1 #get libnetwork packages -clone git github.com/docker/libnetwork v0.7.0-dev.9 +clone git github.com/docker/libnetwork v0.7.0-dev.10 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4 diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index a25b8dd1c8..6675cf1d26 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -1144,10 +1144,10 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContaine func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIP(c *check.C) { // create two networks - dockerCmd(c, "network", "create", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0") + dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0") assertNwIsAvailable(c, "n0") - dockerCmd(c, "network", "create", "--subnet=172.30.0.0/16", "--ip-range=172.30.5.0/24", "--subnet=2001:db8:abcd::/64", "--ip-range=2001:db8:abcd::/80", "n1") + dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--ip-range=172.30.5.0/24", "--subnet=2001:db8:abcd::/64", "--ip-range=2001:db8:abcd::/80", "n1") assertNwIsAvailable(c, "n1") // run a container on first network specifying the ip addresses @@ -1183,7 +1183,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIPStoppedContainer dockerCmd(c, "create", "--name", "c0", "busybox", "top") // create a network - dockerCmd(c, "network", "create", "--subnet=172.30.0.0/16", "--subnet=2001:db8:abcd::/64", "n0") + dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--subnet=2001:db8:abcd::/64", "n0") assertNwIsAvailable(c, "n0") // connect the container to the network specifying an ip addresses diff --git a/vendor/src/github.com/docker/libnetwork/CHANGELOG.md b/vendor/src/github.com/docker/libnetwork/CHANGELOG.md index a46131079e..08f9ceb4ae 100644 --- a/vendor/src/github.com/docker/libnetwork/CHANGELOG.md +++ b/vendor/src/github.com/docker/libnetwork/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.7.0-dev.10 (2016-03-21) +- Add IPv6 service discovery (AAAA records) in embedded DNS server +- Honor enableIPv6 flag in network create for the IP allocation +- Avoid V6 queries in docker domain going to external nameservers + ## 0.7.0-dev.9 (2016-03-18) - Support labels on networks diff --git a/vendor/src/github.com/docker/libnetwork/network.go b/vendor/src/github.com/docker/libnetwork/network.go index e4b6e4adaa..ed2b52c790 100644 --- a/vendor/src/github.com/docker/libnetwork/network.go +++ b/vendor/src/github.com/docker/libnetwork/network.go @@ -71,8 +71,9 @@ type NetworkInfo interface { type EndpointWalker func(ep Endpoint) bool type svcInfo struct { - svcMap map[string][]net.IP - ipMap map[string]string + svcMap map[string][]net.IP + svcIPv6Map map[string][]net.IP + ipMap map[string]string } // IpamConf contains all the ipam related configurations for a network @@ -489,6 +490,10 @@ func (n *network) UnmarshalJSON(b []byte) (err error) { if v, ok := netMap["inDelete"]; ok { n.inDelete = v.(bool) } + // Reconcile old networks with the recently added `--ipv6` flag + if !n.enableIPv6 { + n.enableIPv6 = len(n.ipamV6Info) > 0 + } return nil } @@ -779,7 +784,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi ep.ipamOptions[netlabel.MacAddress] = ep.iface.mac.String() } - if err = ep.assignAddress(ipam.driver, true, !n.postIPv6); err != nil { + if err = ep.assignAddress(ipam.driver, true, n.enableIPv6 && !n.postIPv6); err != nil { return nil, err } defer func() { @@ -799,7 +804,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi } }() - if err = ep.assignAddress(ipam.driver, false, n.postIPv6); err != nil { + if err = ep.assignAddress(ipam.driver, false, n.enableIPv6 && n.postIPv6); err != nil { return nil, err } @@ -890,68 +895,103 @@ func (n *network) EndpointByID(id string) (Endpoint, error) { } func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool) { + var ipv6 net.IP epName := ep.Name() if iface := ep.Iface(); iface.Address() != nil { myAliases := ep.MyAliases() + if iface.AddressIPv6() != nil { + ipv6 = iface.AddressIPv6().IP + } + if isAdd { // If anonymous endpoint has an alias use the first alias // for ip->name mapping. Not having the reverse mapping // breaks some apps if ep.isAnonymous() { if len(myAliases) > 0 { - n.addSvcRecords(myAliases[0], iface.Address().IP, true) + n.addSvcRecords(myAliases[0], iface.Address().IP, ipv6, true) } } else { - n.addSvcRecords(epName, iface.Address().IP, true) + n.addSvcRecords(epName, iface.Address().IP, ipv6, true) } for _, alias := range myAliases { - n.addSvcRecords(alias, iface.Address().IP, false) + n.addSvcRecords(alias, iface.Address().IP, ipv6, false) } } else { if ep.isAnonymous() { if len(myAliases) > 0 { - n.deleteSvcRecords(myAliases[0], iface.Address().IP, true) + n.deleteSvcRecords(myAliases[0], iface.Address().IP, ipv6, true) } } else { - n.deleteSvcRecords(epName, iface.Address().IP, true) + n.deleteSvcRecords(epName, iface.Address().IP, ipv6, true) } for _, alias := range myAliases { - n.deleteSvcRecords(alias, iface.Address().IP, false) + n.deleteSvcRecords(alias, iface.Address().IP, ipv6, false) } } } } -func (n *network) addSvcRecords(name string, epIP net.IP, ipMapUpdate bool) { +func addIPToName(ipMap map[string]string, name string, ip net.IP) { + reverseIP := netutils.ReverseIP(ip.String()) + if _, ok := ipMap[reverseIP]; !ok { + ipMap[reverseIP] = name + } +} + +func addNameToIP(svcMap map[string][]net.IP, name string, epIP net.IP) { + ipList := svcMap[name] + for _, ip := range ipList { + if ip.Equal(epIP) { + return + } + } + svcMap[name] = append(svcMap[name], epIP) +} + +func delNameToIP(svcMap map[string][]net.IP, name string, epIP net.IP) { + ipList := svcMap[name] + for i, ip := range ipList { + if ip.Equal(epIP) { + ipList = append(ipList[:i], ipList[i+1:]...) + break + } + } + svcMap[name] = ipList + + if len(ipList) == 0 { + delete(svcMap, name) + } +} + +func (n *network) addSvcRecords(name string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool) { c := n.getController() c.Lock() defer c.Unlock() sr, ok := c.svcDb[n.ID()] if !ok { sr = svcInfo{ - svcMap: make(map[string][]net.IP), - ipMap: make(map[string]string), + svcMap: make(map[string][]net.IP), + svcIPv6Map: make(map[string][]net.IP), + ipMap: make(map[string]string), } c.svcDb[n.ID()] = sr } if ipMapUpdate { - reverseIP := netutils.ReverseIP(epIP.String()) - if _, ok := sr.ipMap[reverseIP]; !ok { - sr.ipMap[reverseIP] = name + addIPToName(sr.ipMap, name, epIP) + if epIPv6 != nil { + addIPToName(sr.ipMap, name, epIPv6) } } - ipList := sr.svcMap[name] - for _, ip := range ipList { - if ip.Equal(epIP) { - return - } + addNameToIP(sr.svcMap, name, epIP) + if epIPv6 != nil { + addNameToIP(sr.svcIPv6Map, name, epIPv6) } - sr.svcMap[name] = append(sr.svcMap[name], epIP) } -func (n *network) deleteSvcRecords(name string, epIP net.IP, ipMapUpdate bool) { +func (n *network) deleteSvcRecords(name string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool) { c := n.getController() c.Lock() defer c.Unlock() @@ -962,19 +1002,16 @@ func (n *network) deleteSvcRecords(name string, epIP net.IP, ipMapUpdate bool) { if ipMapUpdate { delete(sr.ipMap, netutils.ReverseIP(epIP.String())) - } - ipList := sr.svcMap[name] - for i, ip := range ipList { - if ip.Equal(epIP) { - ipList = append(ipList[:i], ipList[i+1:]...) - break + if epIPv6 != nil { + delete(sr.ipMap, netutils.ReverseIP(epIPv6.String())) } } - sr.svcMap[name] = ipList - if len(ipList) == 0 { - delete(sr.svcMap, name) + delNameToIP(sr.svcMap, name, epIP) + + if epIPv6 != nil { + delNameToIP(sr.svcIPv6Map, name, epIPv6) } } @@ -1033,6 +1070,10 @@ func (n *network) ipamAllocate() error { } }() + if !n.enableIPv6 { + return nil + } + return n.ipamAllocateVersion(6, ipam) } @@ -1153,7 +1194,7 @@ func (n *network) ipamReleaseVersion(ipVer int, ipam ipamapi.Ipam) { return } - if *infoList == nil { + if len(*infoList) == 0 { return } diff --git a/vendor/src/github.com/docker/libnetwork/resolver.go b/vendor/src/github.com/docker/libnetwork/resolver.go index 854ef295bd..177d0a8b83 100644 --- a/vendor/src/github.com/docker/libnetwork/resolver.go +++ b/vendor/src/github.com/docker/libnetwork/resolver.go @@ -10,6 +10,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/iptables" + "github.com/docker/libnetwork/netutils" "github.com/miekg/dns" ) @@ -185,27 +186,46 @@ func shuffleAddr(addr []net.IP) []net.IP { return addr } -func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error) { - addr := r.sb.ResolveName(name) +func createRespMsg(query *dns.Msg) *dns.Msg { + resp := new(dns.Msg) + resp.SetReply(query) + setCommonFlags(resp) + + return resp +} + +func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns.Msg, error) { + addr, ipv6Miss := r.sb.ResolveName(name, ipType) + if addr == nil && ipv6Miss { + // Send a reply without any Answer sections + log.Debugf("Lookup name %s present without IPv6 address", name) + resp := createRespMsg(query) + return resp, nil + } if addr == nil { return nil, nil } log.Debugf("Lookup for %s: IP %v", name, addr) - resp := new(dns.Msg) - resp.SetReply(query) - setCommonFlags(resp) - + resp := createRespMsg(query) if len(addr) > 1 { addr = shuffleAddr(addr) } - - for _, ip := range addr { - rr := new(dns.A) - rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL} - rr.A = ip - resp.Answer = append(resp.Answer, rr) + if ipType == netutils.IPv4 { + for _, ip := range addr { + rr := new(dns.A) + rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL} + rr.A = ip + resp.Answer = append(resp.Answer, rr) + } + } else { + for _, ip := range addr { + rr := new(dns.AAAA) + rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: respTTL} + rr.AAAA = ip + resp.Answer = append(resp.Answer, rr) + } } return resp, nil } @@ -264,7 +284,9 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) { } name := query.Question[0].Name if query.Question[0].Qtype == dns.TypeA { - resp, err = r.handleIPv4Query(name, query) + resp, err = r.handleIPQuery(name, query, netutils.IPv4) + } else if query.Question[0].Qtype == dns.TypeAAAA { + resp, err = r.handleIPQuery(name, query, netutils.IPv6) } else if query.Question[0].Qtype == dns.TypePTR { resp, err = r.handlePTRQuery(name, query) } diff --git a/vendor/src/github.com/docker/libnetwork/sandbox.go b/vendor/src/github.com/docker/libnetwork/sandbox.go index 5733deac18..7fc5bdeead 100644 --- a/vendor/src/github.com/docker/libnetwork/sandbox.go +++ b/vendor/src/github.com/docker/libnetwork/sandbox.go @@ -11,6 +11,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/etchosts" "github.com/docker/libnetwork/netlabel" + "github.com/docker/libnetwork/netutils" "github.com/docker/libnetwork/osl" "github.com/docker/libnetwork/types" ) @@ -36,9 +37,11 @@ type Sandbox interface { Rename(name string) error // Delete destroys this container after detaching it from all connected endpoints. Delete() error - // ResolveName searches for the service name in the networks to which the sandbox - // is connected to. - ResolveName(name string) []net.IP + // ResolveName resolves a service name to an IPv4 or IPv6 address by searching + // the networks the sandbox is connected to. For IPv6 queries, second return + // value will be true if the name exists in docker domain but doesn't have an + // IPv6 address. Such queries shouldn't be forwarded to external nameservers. + ResolveName(name string, iplen int) ([]net.IP, bool) // ResolveIP returns the service name for the passed in IP. IP is in reverse dotted // notation; the format used for DNS PTR records ResolveIP(name string) string @@ -418,9 +421,7 @@ func (sb *sandbox) execFunc(f func()) { sb.osSbox.InvokeFunc(f) } -func (sb *sandbox) ResolveName(name string) []net.IP { - var ip []net.IP - +func (sb *sandbox) ResolveName(name string, ipType int) ([]net.IP, bool) { // Embedded server owns the docker network domain. Resolution should work // for both container_name and container_name.network_name // We allow '.' in service name and network name. For a name a.b.c.d the @@ -453,21 +454,29 @@ func (sb *sandbox) ResolveName(name string) []net.IP { log.Debugf("To resolve: %v in %v", reqName[i], networkName[i]) // First check for local container alias - ip = sb.resolveName(reqName[i], networkName[i], epList, true) + ip, ipv6Miss := sb.resolveName(reqName[i], networkName[i], epList, true, ipType) if ip != nil { - return ip + return ip, false + } + if ipv6Miss { + return ip, ipv6Miss } // Resolve the actual container name - ip = sb.resolveName(reqName[i], networkName[i], epList, false) + ip, ipv6Miss = sb.resolveName(reqName[i], networkName[i], epList, false, ipType) if ip != nil { - return ip + return ip, false + } + if ipv6Miss { + return ip, ipv6Miss } } - return nil + return nil, false } -func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool) []net.IP { +func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool, ipType int) ([]net.IP, bool) { + var ipv6Miss bool + for _, ep := range epList { name := req n := ep.getNetwork() @@ -504,14 +513,26 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin continue } + var ip []net.IP n.Lock() - ip, ok := sr.svcMap[name] + ip, ok = sr.svcMap[name] + + if ipType == netutils.IPv6 { + // If the name resolved to v4 address then its a valid name in + // the docker network domain. If the network is not v6 enabled + // set ipv6Miss to filter the DNS query from going to external + // resolvers. + if ok && n.enableIPv6 == false { + ipv6Miss = true + } + ip = sr.svcIPv6Map[name] + } n.Unlock() - if ok { - return ip + if ip != nil { + return ip, false } } - return nil + return nil, ipv6Miss } func (sb *sandbox) SetKey(basePath string) error {