Skip to content

Commit

Permalink
Merge pull request #1586 from sanimej/ptr
Browse files Browse the repository at this point in the history
Defer PTR queries to external servers based on A/AAAA response
  • Loading branch information
aboch committed Dec 21, 2016
2 parents ee7cbfb + 805efb1 commit c4aa329
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 20 deletions.
2 changes: 1 addition & 1 deletion libnetwork_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ func TestSRVServiceQuery(t *testing.T) {
sr := svcInfo{
svcMap: make(map[string][]net.IP),
svcIPv6Map: make(map[string][]net.IP),
ipMap: make(map[string]string),
ipMap: make(map[string]*ipInfo),
service: make(map[string][]servicePorts),
}
// backing container for the service
Expand Down
55 changes: 38 additions & 17 deletions network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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,
}
}
}

Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -1612,16 +1622,15 @@ 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
}

req = strings.TrimSuffix(req, ".")
var ip []net.IP
n.Lock()
ip, ok = sr.svcMap[req]

if ipType == types.IPv6 {
Expand All @@ -1634,7 +1643,6 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) {
}
ip = sr.svcIPv6Map[req]
}
n.Unlock()

if ip != nil {
return ip, false
Expand All @@ -1643,29 +1651,42 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) {
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 ""
}

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) {
Expand All @@ -1689,8 +1710,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
Expand Down
18 changes: 16 additions & 2 deletions resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -462,9 +465,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
}
Expand Down
7 changes: 7 additions & 0 deletions sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit c4aa329

Please sign in to comment.