mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #870 from sanimej/bugs
Adds AAAA record handling for the embedded DNS
This commit is contained in:
commit
22fae3ae2c
4 changed files with 98 additions and 48 deletions
|
@ -1216,7 +1216,7 @@ func (f *fakeSandbox) SetKey(key string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeSandbox) ResolveName(name string) []net.IP {
|
func (f *fakeSandbox) ResolveName(name string, ipType int) []net.IP {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,9 @@ type NetworkInfo interface {
|
||||||
type EndpointWalker func(ep Endpoint) bool
|
type EndpointWalker func(ep Endpoint) bool
|
||||||
|
|
||||||
type svcInfo struct {
|
type svcInfo struct {
|
||||||
svcMap map[string][]net.IP
|
svcMap map[string][]net.IP
|
||||||
ipMap map[string]string
|
svcIPv6Map map[string][]net.IP
|
||||||
|
ipMap map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// IpamConf contains all the ipam related configurations for a network
|
// IpamConf contains all the ipam related configurations for a network
|
||||||
|
@ -894,68 +895,103 @@ func (n *network) EndpointByID(id string) (Endpoint, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool) {
|
func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool) {
|
||||||
|
var ipv6 net.IP
|
||||||
epName := ep.Name()
|
epName := ep.Name()
|
||||||
if iface := ep.Iface(); iface.Address() != nil {
|
if iface := ep.Iface(); iface.Address() != nil {
|
||||||
myAliases := ep.MyAliases()
|
myAliases := ep.MyAliases()
|
||||||
|
if iface.AddressIPv6() != nil {
|
||||||
|
ipv6 = iface.AddressIPv6().IP
|
||||||
|
}
|
||||||
|
|
||||||
if isAdd {
|
if isAdd {
|
||||||
// If anonymous endpoint has an alias use the first alias
|
// If anonymous endpoint has an alias use the first alias
|
||||||
// for ip->name mapping. Not having the reverse mapping
|
// for ip->name mapping. Not having the reverse mapping
|
||||||
// breaks some apps
|
// breaks some apps
|
||||||
if ep.isAnonymous() {
|
if ep.isAnonymous() {
|
||||||
if len(myAliases) > 0 {
|
if len(myAliases) > 0 {
|
||||||
n.addSvcRecords(myAliases[0], iface.Address().IP, true)
|
n.addSvcRecords(myAliases[0], iface.Address().IP, ipv6, true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n.addSvcRecords(epName, iface.Address().IP, true)
|
n.addSvcRecords(epName, iface.Address().IP, ipv6, true)
|
||||||
}
|
}
|
||||||
for _, alias := range myAliases {
|
for _, alias := range myAliases {
|
||||||
n.addSvcRecords(alias, iface.Address().IP, false)
|
n.addSvcRecords(alias, iface.Address().IP, ipv6, false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ep.isAnonymous() {
|
if ep.isAnonymous() {
|
||||||
if len(myAliases) > 0 {
|
if len(myAliases) > 0 {
|
||||||
n.deleteSvcRecords(myAliases[0], iface.Address().IP, true)
|
n.deleteSvcRecords(myAliases[0], iface.Address().IP, ipv6, true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n.deleteSvcRecords(epName, iface.Address().IP, true)
|
n.deleteSvcRecords(epName, iface.Address().IP, ipv6, true)
|
||||||
}
|
}
|
||||||
for _, alias := range myAliases {
|
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 := n.getController()
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
sr, ok := c.svcDb[n.ID()]
|
sr, ok := c.svcDb[n.ID()]
|
||||||
if !ok {
|
if !ok {
|
||||||
sr = svcInfo{
|
sr = svcInfo{
|
||||||
svcMap: make(map[string][]net.IP),
|
svcMap: make(map[string][]net.IP),
|
||||||
ipMap: make(map[string]string),
|
svcIPv6Map: make(map[string][]net.IP),
|
||||||
|
ipMap: make(map[string]string),
|
||||||
}
|
}
|
||||||
c.svcDb[n.ID()] = sr
|
c.svcDb[n.ID()] = sr
|
||||||
}
|
}
|
||||||
|
|
||||||
if ipMapUpdate {
|
if ipMapUpdate {
|
||||||
reverseIP := netutils.ReverseIP(epIP.String())
|
addIPToName(sr.ipMap, name, epIP)
|
||||||
if _, ok := sr.ipMap[reverseIP]; !ok {
|
if epIPv6 != nil {
|
||||||
sr.ipMap[reverseIP] = name
|
addIPToName(sr.ipMap, name, epIPv6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipList := sr.svcMap[name]
|
addNameToIP(sr.svcMap, name, epIP)
|
||||||
for _, ip := range ipList {
|
if epIPv6 != nil {
|
||||||
if ip.Equal(epIP) {
|
addNameToIP(sr.svcIPv6Map, name, epIPv6)
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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 := n.getController()
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
@ -966,19 +1002,16 @@ func (n *network) deleteSvcRecords(name string, epIP net.IP, ipMapUpdate bool) {
|
||||||
|
|
||||||
if ipMapUpdate {
|
if ipMapUpdate {
|
||||||
delete(sr.ipMap, netutils.ReverseIP(epIP.String()))
|
delete(sr.ipMap, netutils.ReverseIP(epIP.String()))
|
||||||
}
|
|
||||||
|
|
||||||
ipList := sr.svcMap[name]
|
if epIPv6 != nil {
|
||||||
for i, ip := range ipList {
|
delete(sr.ipMap, netutils.ReverseIP(epIPv6.String()))
|
||||||
if ip.Equal(epIP) {
|
|
||||||
ipList = append(ipList[:i], ipList[i+1:]...)
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sr.svcMap[name] = ipList
|
|
||||||
|
|
||||||
if len(ipList) == 0 {
|
delNameToIP(sr.svcMap, name, epIP)
|
||||||
delete(sr.svcMap, name)
|
|
||||||
|
if epIPv6 != nil {
|
||||||
|
delNameToIP(sr.svcIPv6Map, name, epIPv6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libnetwork/iptables"
|
"github.com/docker/libnetwork/iptables"
|
||||||
|
"github.com/docker/libnetwork/netutils"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -185,8 +186,8 @@ func shuffleAddr(addr []net.IP) []net.IP {
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error) {
|
func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns.Msg, error) {
|
||||||
addr := r.sb.ResolveName(name)
|
addr := r.sb.ResolveName(name, ipType)
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -200,12 +201,20 @@ func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error
|
||||||
if len(addr) > 1 {
|
if len(addr) > 1 {
|
||||||
addr = shuffleAddr(addr)
|
addr = shuffleAddr(addr)
|
||||||
}
|
}
|
||||||
|
if ipType == netutils.IPv4 {
|
||||||
for _, ip := range addr {
|
for _, ip := range addr {
|
||||||
rr := new(dns.A)
|
rr := new(dns.A)
|
||||||
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
||||||
rr.A = ip
|
rr.A = ip
|
||||||
resp.Answer = append(resp.Answer, rr)
|
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
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
@ -264,7 +273,9 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
||||||
}
|
}
|
||||||
name := query.Question[0].Name
|
name := query.Question[0].Name
|
||||||
if query.Question[0].Qtype == dns.TypeA {
|
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 {
|
} else if query.Question[0].Qtype == dns.TypePTR {
|
||||||
resp, err = r.handlePTRQuery(name, query)
|
resp, err = r.handlePTRQuery(name, query)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libnetwork/etchosts"
|
"github.com/docker/libnetwork/etchosts"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
|
"github.com/docker/libnetwork/netutils"
|
||||||
"github.com/docker/libnetwork/osl"
|
"github.com/docker/libnetwork/osl"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
)
|
)
|
||||||
|
@ -36,9 +37,9 @@ type Sandbox interface {
|
||||||
Rename(name string) error
|
Rename(name string) error
|
||||||
// Delete destroys this container after detaching it from all connected endpoints.
|
// Delete destroys this container after detaching it from all connected endpoints.
|
||||||
Delete() error
|
Delete() error
|
||||||
// ResolveName searches for the service name in the networks to which the sandbox
|
// ResolveName resolves a service name to an IPv4 or IPv6 address by searching the
|
||||||
// is connected to.
|
// networks the sandbox is connected to.
|
||||||
ResolveName(name string) []net.IP
|
ResolveName(name string, iplen int) []net.IP
|
||||||
// ResolveIP returns the service name for the passed in IP. IP is in reverse dotted
|
// ResolveIP returns the service name for the passed in IP. IP is in reverse dotted
|
||||||
// notation; the format used for DNS PTR records
|
// notation; the format used for DNS PTR records
|
||||||
ResolveIP(name string) string
|
ResolveIP(name string) string
|
||||||
|
@ -418,7 +419,7 @@ func (sb *sandbox) execFunc(f func()) {
|
||||||
sb.osSbox.InvokeFunc(f)
|
sb.osSbox.InvokeFunc(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sb *sandbox) ResolveName(name string) []net.IP {
|
func (sb *sandbox) ResolveName(name string, ipType int) []net.IP {
|
||||||
var ip []net.IP
|
var ip []net.IP
|
||||||
|
|
||||||
// Embedded server owns the docker network domain. Resolution should work
|
// Embedded server owns the docker network domain. Resolution should work
|
||||||
|
@ -453,13 +454,13 @@ func (sb *sandbox) ResolveName(name string) []net.IP {
|
||||||
log.Debugf("To resolve: %v in %v", reqName[i], networkName[i])
|
log.Debugf("To resolve: %v in %v", reqName[i], networkName[i])
|
||||||
|
|
||||||
// First check for local container alias
|
// First check for local container alias
|
||||||
ip = sb.resolveName(reqName[i], networkName[i], epList, true)
|
ip = sb.resolveName(reqName[i], networkName[i], epList, true, ipType)
|
||||||
if ip != nil {
|
if ip != nil {
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the actual container name
|
// Resolve the actual container name
|
||||||
ip = sb.resolveName(reqName[i], networkName[i], epList, false)
|
ip = sb.resolveName(reqName[i], networkName[i], epList, false, ipType)
|
||||||
if ip != nil {
|
if ip != nil {
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
@ -467,7 +468,7 @@ func (sb *sandbox) ResolveName(name string) []net.IP {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
for _, ep := range epList {
|
for _, ep := range epList {
|
||||||
name := req
|
name := req
|
||||||
n := ep.getNetwork()
|
n := ep.getNetwork()
|
||||||
|
@ -504,8 +505,13 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ip []net.IP
|
||||||
n.Lock()
|
n.Lock()
|
||||||
ip, ok := sr.svcMap[name]
|
if ipType == netutils.IPv6 {
|
||||||
|
ip, ok = sr.svcIPv6Map[name]
|
||||||
|
} else {
|
||||||
|
ip, ok = sr.svcMap[name]
|
||||||
|
}
|
||||||
n.Unlock()
|
n.Unlock()
|
||||||
if ok {
|
if ok {
|
||||||
return ip
|
return ip
|
||||||
|
|
Loading…
Reference in a new issue