Improve DNS output: distinguish NS resolution failures from domain errors (#20)
CI / test (push) Failing after 2m19s
CI / test (push) Failing after 2m19s
This commit was merged in pull request #20.
This commit is contained in:
@@ -144,6 +144,8 @@ func summaryTypeLabel(respType string) string {
|
|||||||
return "query type not implemented by server"
|
return "query type not implemented by server"
|
||||||
case "cname_loop":
|
case "cname_loop":
|
||||||
return "resulted in a CNAME loop"
|
return "resulted in a CNAME loop"
|
||||||
|
case "ns_error":
|
||||||
|
return "nameserver lookup failed"
|
||||||
case "error":
|
case "error":
|
||||||
return "resulted in an error"
|
return "resulted in an error"
|
||||||
case "referral":
|
case "referral":
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ func TestSummaryTypeLabelAllTypes(t *testing.T) {
|
|||||||
"refused": "query refused by server",
|
"refused": "query refused by server",
|
||||||
"notimp": "query type not implemented by server",
|
"notimp": "query type not implemented by server",
|
||||||
"cname_loop": "resulted in a CNAME loop",
|
"cname_loop": "resulted in a CNAME loop",
|
||||||
|
"ns_error": "nameserver lookup failed",
|
||||||
"error": "resulted in an error",
|
"error": "resulted in an error",
|
||||||
"referral": "resulted in a referral",
|
"referral": "resulted in a referral",
|
||||||
"unknown_type": "unknown_type",
|
"unknown_type": "unknown_type",
|
||||||
|
|||||||
@@ -220,6 +220,12 @@ func (f *textFormatter) formatResultLine(result traverse.TraversalResult) string
|
|||||||
msg = result.Response.ErrorMessage
|
msg = result.Response.ErrorMessage
|
||||||
}
|
}
|
||||||
return f.colorize(fmt.Sprintf("%s %s", prob, msg), colorRed)
|
return f.colorize(fmt.Sprintf("%s %s", prob, msg), colorRed)
|
||||||
|
case traverse.RespNSResolutionFailed:
|
||||||
|
msg := "nameserver lookup failed"
|
||||||
|
if result.Response.ErrorMessage != "" {
|
||||||
|
msg = result.Response.ErrorMessage
|
||||||
|
}
|
||||||
|
return f.colorize(fmt.Sprintf("%s %s", prob, msg), colorYellow)
|
||||||
case traverse.RespError:
|
case traverse.RespError:
|
||||||
msg := "resulted in an error"
|
msg := "resulted in an error"
|
||||||
if result.Response.ErrorMessage != "" {
|
if result.Response.ErrorMessage != "" {
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ Answers: []miekgdns.RR{
|
|||||||
{"refused", traverse.RespREFUSED, nil, ""},
|
{"refused", traverse.RespREFUSED, nil, ""},
|
||||||
{"notimp", traverse.RespNOTIMPL, nil, ""},
|
{"notimp", traverse.RespNOTIMPL, nil, ""},
|
||||||
{"cname_loop", traverse.RespCNAMELoop, nil, "loop detected"},
|
{"cname_loop", traverse.RespCNAMELoop, nil, "loop detected"},
|
||||||
|
{"ns_error", traverse.RespNSResolutionFailed, nil, "nameserver ns1.example.com could not be resolved"},
|
||||||
{"error", traverse.RespError, nil, "something went wrong"},
|
{"error", traverse.RespError, nil, "something went wrong"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ const (
|
|||||||
RespNOTIMPL
|
RespNOTIMPL
|
||||||
RespCNAMELoop
|
RespCNAMELoop
|
||||||
RespError
|
RespError
|
||||||
|
// RespNSResolutionFailed indicates that the traversal could not resolve the
|
||||||
|
// IP address of an in-bailiwick nameserver. The domain may still be
|
||||||
|
// reachable in practice (e.g. via glue records held by the registry), but
|
||||||
|
// the iterative traversal could not complete that path.
|
||||||
|
RespNSResolutionFailed
|
||||||
)
|
)
|
||||||
|
|
||||||
func (rt ResponseType) String() string {
|
func (rt ResponseType) String() string {
|
||||||
@@ -44,6 +49,8 @@ func (rt ResponseType) String() string {
|
|||||||
return "cname_loop"
|
return "cname_loop"
|
||||||
case RespError:
|
case RespError:
|
||||||
return "error"
|
return "error"
|
||||||
|
case RespNSResolutionFailed:
|
||||||
|
return "ns_error"
|
||||||
default:
|
default:
|
||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
@@ -231,7 +238,7 @@ func (r *Response) resolveGlue(child *Referral) {
|
|||||||
|
|
||||||
func (r *Response) IsTerminal() bool {
|
func (r *Response) IsTerminal() bool {
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case RespAnswer, RespNODATA, RespNXDOMAIN, RespSERVFAIL, RespREFUSED, RespNOTIMPL, RespCNAMELoop, RespError:
|
case RespAnswer, RespNODATA, RespNXDOMAIN, RespSERVFAIL, RespREFUSED, RespNOTIMPL, RespCNAMELoop, RespError, RespNSResolutionFailed:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ func TestResponseIsTerminal(t *testing.T) {
|
|||||||
{RespNXDOMAIN, true},
|
{RespNXDOMAIN, true},
|
||||||
{RespSERVFAIL, true},
|
{RespSERVFAIL, true},
|
||||||
{RespError, true},
|
{RespError, true},
|
||||||
|
{RespNSResolutionFailed, true},
|
||||||
{RespReferral, false},
|
{RespReferral, false},
|
||||||
{RespCNAMEFollow, false},
|
{RespCNAMEFollow, false},
|
||||||
}
|
}
|
||||||
@@ -272,6 +273,7 @@ func TestResponseTypeString(t *testing.T) {
|
|||||||
{RespNXDOMAIN, "nxdomain"},
|
{RespNXDOMAIN, "nxdomain"},
|
||||||
{RespSERVFAIL, "servfail"},
|
{RespSERVFAIL, "servfail"},
|
||||||
{RespError, "error"},
|
{RespError, "error"},
|
||||||
|
{RespNSResolutionFailed, "ns_error"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -231,10 +232,15 @@ func (t *Traverser) processReferral(ctx context.Context, ref *Referral, cache *I
|
|||||||
ref.State = StateResolved
|
ref.State = StateResolved
|
||||||
} else {
|
} else {
|
||||||
addrs, err := t.ResolveNS(ctx, ref.Name, cache, visitedCopy, t.depth)
|
addrs, err := t.ResolveNS(ctx, ref.Name, cache, visitedCopy, t.depth)
|
||||||
|
nsName := strings.TrimSuffix(ref.Bailiwick, ".")
|
||||||
|
if nsName == "" || nsName == "." {
|
||||||
|
nsName = strings.TrimSuffix(ref.Name, ".")
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Response{
|
return &Response{
|
||||||
Referral: ref,
|
Referral: ref,
|
||||||
Type: RespError,
|
Type: RespNSResolutionFailed,
|
||||||
|
ErrorMessage: fmt.Sprintf("nameserver %s could not be resolved", nsName),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(addrs) > 0 {
|
if len(addrs) > 0 {
|
||||||
@@ -243,7 +249,8 @@ func (t *Traverser) processReferral(ctx context.Context, ref *Referral, cache *I
|
|||||||
} else {
|
} else {
|
||||||
return &Response{
|
return &Response{
|
||||||
Referral: ref,
|
Referral: ref,
|
||||||
Type: RespError,
|
Type: RespNSResolutionFailed,
|
||||||
|
ErrorMessage: fmt.Sprintf("nameserver %s could not be resolved", nsName),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -360,7 +367,7 @@ func (t *Traverser) ResolveNS(ctx context.Context, nsName string, cache *InfoCac
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp.Type == RespSERVFAIL || resp.Type == RespError {
|
if resp.Type == RespSERVFAIL || resp.Type == RespError || resp.Type == RespNSResolutionFailed {
|
||||||
lastErr = fmt.Errorf("server error resolving %s: %s", nsName, resp.Type)
|
lastErr = fmt.Errorf("server error resolving %s: %s", nsName, resp.Type)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user