diff --git a/netutil/addr.go b/netutil/addr.go index de176b8..51cada4 100644 --- a/netutil/addr.go +++ b/netutil/addr.go @@ -3,13 +3,13 @@ package netutil import ( - "errors" "fmt" "net" "net/url" "strconv" "strings" + "github.com/AdguardTeam/golibs/errors" "golang.org/x/exp/slices" "golang.org/x/net/idna" ) @@ -164,6 +164,37 @@ func ValidateMAC(mac net.HardwareAddr) (err error) { // [RFC 1035]: https://datatracker.ietf.org/doc/html/rfc1035 const MaxDomainLabelLen = 63 +// ValidateTLDLabel validates the top-level domain label in accordance to [RFC +// 3696 Section 2]. In addition to the validations performed by +// [ValidateHostnameLabel], it also checks that the label contains at least one +// non-digit character. +// +// Any error returned will have the underlying type of [*LabelError]. +// +// [RFC 3696 Section 2]: https://datatracker.ietf.org/doc/html/rfc3696#section-2 +func ValidateTLDLabel(tld string) (err error) { + defer makeLabelError(&err, tld, LabelKindTLD) + + if err = ValidateHostnameLabel(tld); err != nil { + err = errors.Unwrap(err) + replaceKind(err, LabelKindTLD) + + return err + } + + for _, r := range tld { + if r < '0' || r > '9' { + return nil + } + } + + // There is a requirement for top-level domain label to contain at least one + // non-digit character. See [RFC 3696 Section 2]. + // + // [RFC 3696 Section 2]: https://datatracker.ietf.org/doc/html/rfc3696#section-2 + return errors.Error("all octets are numeric") +} + // MaxDomainNameLen is the maximum allowed length of a full domain name // according to [RFC 1035]. // @@ -172,12 +203,56 @@ const MaxDomainLabelLen = 63 // [RFC 1035]: https://datatracker.ietf.org/doc/html/rfc1035 const MaxDomainNameLen = 253 -// ValidateDomainNameLabel returns an error if label is not a valid label of -// a domain name. An empty label is considered invalid. +// ValidateDomainName validates the domain name in accordance to [RFC 1035] and +// [RFC 3696 Section 2]. As opposed to [ValidateHostname], this function only +// validates the lengths of the name itself and its labels, except the TLD. // // Any error returned will have the underlying type of [*AddrError]. +// +// [RFC 1035]: https://datatracker.ietf.org/doc/html/rfc1035 +// [RFC 3696 Section 2]: https://datatracker.ietf.org/doc/html/rfc3696#section-2 +func ValidateDomainName(name string) (err error) { + defer makeAddrError(&err, name, AddrKindDomainName) + + name, err = idna.ToASCII(name) + if err != nil { + return err + } + + if name == "" { + return ErrAddrIsEmpty + } else if l := len(name); l > MaxDomainNameLen { + return &LengthError{ + Kind: AddrKindDomainName, + Max: MaxDomainNameLen, + Length: l, + } + } + + labels := strings.Split(name, ".") + tldIdx := len(labels) - 1 + for _, l := range labels[:tldIdx] { + err = ValidateDomainNameLabel(l) + if err != nil { + return err + } + } + + // Use stricter rules for the TLD. + return ValidateTLDLabel(labels[tldIdx]) +} + +// ValidateDomainNameLabel returns an error if label is not a valid label of a +// domain name. An empty label is considered invalid. Essentially it validates +// the length of the label since the name in DNS is permitted to contain any +// printable ASCII character, see [RFC 3696 Section 2]. label must only contain +// ASCII characters, see [idna.ToASCII]. +// +// Any error returned will have the underlying type of [*LabelError]. +// +// [RFC 3696 Section 2]: https://datatracker.ietf.org/doc/html/rfc3696#section-2 func ValidateDomainNameLabel(label string) (err error) { - defer makeAddrError(&err, label, AddrKindLabel) + defer makeLabelError(&err, label, LabelKindDomain) if label == "" { return ErrLabelIsEmpty @@ -186,15 +261,35 @@ func ValidateDomainNameLabel(label string) (err error) { l := len(label) if l > MaxDomainLabelLen { return &LengthError{ - Kind: AddrKindLabel, + Kind: LabelKindDomain, Max: MaxDomainLabelLen, Length: l, } } + return nil +} + +// ValidateHostnameLabel returns an error if label is not a valid label of a +// domain name. An empty label is considered invalid. +// +// Any error returned will have the underlying type of [*LabelError]. +func ValidateHostnameLabel(label string) (err error) { + defer makeLabelError(&err, label, LabelKindHost) + + if err = ValidateDomainNameLabel(label); err != nil { + err = errors.Unwrap(err) + if lerr, ok := err.(*LengthError); ok { + lerr.Kind = LabelKindHost + } + + return err + } + + l := len(label) if r := rune(label[0]); !IsValidHostOuterRune(r) { return &RuneError{ - Kind: AddrKindLabel, + Kind: LabelKindHost, Rune: r, } } else if l == 1 { @@ -204,7 +299,7 @@ func ValidateDomainNameLabel(label string) (err error) { for _, r := range label[1 : l-1] { if !IsValidHostInnerRune(r) { return &RuneError{ - Kind: AddrKindLabel, + Kind: LabelKindHost, Rune: r, } } @@ -212,7 +307,7 @@ func ValidateDomainNameLabel(label string) (err error) { if r := rune(label[l-1]); !IsValidHostOuterRune(r) { return &RuneError{ - Kind: AddrKindLabel, + Kind: LabelKindHost, Rune: r, } } @@ -220,16 +315,17 @@ func ValidateDomainNameLabel(label string) (err error) { return nil } -// ValidateDomainName validates the domain name in accordance to RFC 952, -// [RFC 1035], and with [RFC 1123]'s inclusion of digits at the start of the -// host. It doesn't validate against two or more hyphens to allow punycode and +// ValidateHostname validates the domain name in accordance to [RFC 952], [RFC +// 1035], and with [RFC 1123]'s inclusion of digits at the start of the host. +// It doesn't validate against two or more hyphens to allow punycode and // internationalized domains. // // Any error returned will have the underlying type of [*AddrError]. // +// [RFC 952]: https://datatracker.ietf.org/doc/html/rfc952 // [RFC 1035]: https://datatracker.ietf.org/doc/html/rfc1035 // [RFC 1123]: https://datatracker.ietf.org/doc/html/rfc1123 -func ValidateDomainName(name string) (err error) { +func ValidateHostname(name string) (err error) { defer makeAddrError(&err, name, AddrKindName) name, err = idna.ToASCII(name) @@ -248,14 +344,15 @@ func ValidateDomainName(name string) (err error) { } labels := strings.Split(name, ".") - for _, l := range labels { - err = ValidateDomainNameLabel(l) + tldIdx := len(labels) - 1 + for _, l := range labels[:tldIdx] { + err = ValidateHostnameLabel(l) if err != nil { return err } } - return nil + return ValidateTLDLabel(labels[tldIdx]) } // MaxServiceLabelLen is the maximum allowed length of a service name label @@ -267,15 +364,15 @@ const MaxServiceLabelLen = 16 // ValidateServiceNameLabel returns an error if label is not a valid label of // a service domain name. An empty label is considered invalid. // -// Any error returned will have the underlying type of [*AddrError]. +// Any error returned will have the underlying type of [*LabelError]. func ValidateServiceNameLabel(label string) (err error) { - defer makeAddrError(&err, label, AddrKindSRVLabel) + defer makeLabelError(&err, label, LabelKindSRV) - if label == "" { + if label == "" || label == "_" { return ErrLabelIsEmpty } else if r := rune(label[0]); r != '_' { return &RuneError{ - Kind: AddrKindSRVLabel, + Kind: LabelKindSRV, Rune: r, } } @@ -283,7 +380,7 @@ func ValidateServiceNameLabel(label string) (err error) { l := len(label) if l > MaxServiceLabelLen { return &LengthError{ - Kind: AddrKindSRVLabel, + Kind: LabelKindSRV, Max: MaxServiceLabelLen, Length: l, } @@ -291,11 +388,9 @@ func ValidateServiceNameLabel(label string) (err error) { // TODO(e.burkov): Validate adjacent hyphens since service labels can't be // internationalized. See RFC 6336 Section 5.1. - if err = ValidateDomainNameLabel(label[1:]); err != nil { + if err = ValidateHostnameLabel(label[1:]); err != nil { err = errors.Unwrap(err) - if rerr, ok := err.(*RuneError); ok { - rerr.Kind = AddrKindSRVLabel - } + replaceKind(err, LabelKindSRV) return err } @@ -303,12 +398,12 @@ func ValidateServiceNameLabel(label string) (err error) { return nil } -// ValidateSRVDomainName validates of domain name assuming it belongs to the -// superset of service domain names in accordance to [RFC 2782] and [RFC 6763]. -// It doesn't validate against two or more hyphens to allow punycode and -// internationalized domains. +// ValidateSRVDomainName validates name assuming it belongs to the superset of +// service domain names in accordance to [RFC 2782] and [RFC 6763]. It doesn't +// validate against two or more hyphens to allow punycode and internationalized +// domains. // -// Any error returned will have the underlying type of *AddrError. +// Any error returned will have the underlying type of [*AddrError]. // // [RFC 2782]: https://datatracker.ietf.org/doc/html/rfc2782 // [RFC 6763]: https://datatracker.ietf.org/doc/html/rfc6763 @@ -331,16 +426,17 @@ func ValidateSRVDomainName(name string) (err error) { } labels := strings.Split(name, ".") - for _, l := range labels { - if l != "" && l[0] == '_' { + tldIdx := len(labels) - 1 + for _, l := range labels[:tldIdx] { + if strings.HasPrefix(l, "_") { err = ValidateServiceNameLabel(l) } else { - err = ValidateDomainNameLabel(l) + err = ValidateHostnameLabel(l) } if err != nil { return err } } - return nil + return ValidateTLDLabel(labels[tldIdx]) } diff --git a/netutil/addr_test.go b/netutil/addr_test.go index 610cf4e..087714c 100644 --- a/netutil/addr_test.go +++ b/netutil/addr_test.go @@ -204,27 +204,48 @@ func TestValidateDomainName(t *testing.T) { in: "пример.рф", wantErrAs: nil, wantErrMsg: "", + }, { + name: "success_domain_name", + in: "_non-ldh-domain_.tld", + wantErrAs: nil, + wantErrMsg: "", }, { name: "bad_idna", in: "xn---.com", wantErrAs: nil, wantErrMsg: `bad domain name "xn---.com": idna: invalid label "-"`, }, { - name: "success_one", - in: "e", - wantErrAs: nil, - wantErrMsg: "", + name: "bad_tld", + in: "example.com-", + wantErrAs: nil, + wantErrMsg: `bad domain name "example.com-": ` + + `bad top-level domain name label "com-": ` + + `bad top-level domain name label rune '-'`, + }, { + name: "tld_too_long", + in: "example." + longLabel, + wantErrAs: nil, + wantErrMsg: `bad domain name "example.` + longLabel + `": ` + + `bad top-level domain name label "` + longLabel + `": ` + + `top-level domain name label is too long: got 64, max 63`, + }, { + name: "numeric_tld", + in: "example.123", + wantErrAs: new(*netutil.LabelError), + wantErrMsg: `bad domain name "example.123": ` + + `bad top-level domain name label "123": all octets are numeric`, }, { name: "empty", in: "", wantErrAs: new(errors.Error), wantErrMsg: `bad domain name "": address is empty`, }, { - name: "bad_symbol", + name: "tld_only", in: "!!!", wantErrAs: new(*netutil.RuneError), wantErrMsg: `bad domain name "!!!": ` + - `bad domain name label "!!!": bad domain name label rune '!'`, + `bad top-level domain name label "!!!": ` + + `bad top-level domain name label rune '!'`, }, { name: "bad_length", in: longDomainName, @@ -244,24 +265,113 @@ func TestValidateDomainName(t *testing.T) { wantErrAs: new(errors.Error), wantErrMsg: `bad domain name "example..com": ` + `bad domain name label "": label is empty`, + }} + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + err := netutil.ValidateDomainName(tc.in) + testutil.AssertErrorMsg(t, tc.wantErrMsg, err) + + if tc.wantErrAs != nil { + require.Error(t, err) + + assert.ErrorAs(t, err, new(*netutil.AddrError)) + assert.ErrorAs(t, err, tc.wantErrAs) + } + }) + } +} + +func TestValidateHostname(t *testing.T) { + t.Parallel() + + longDomainName := strings.Repeat("a", 255) + longLabel := strings.Repeat("a", 64) + longLabelDomainName := longLabel + ".com" + + testCases := []struct { + name string + in string + wantErrAs any + wantErrMsg string + }{{ + name: "success", + in: "example.com", + wantErrAs: nil, + wantErrMsg: "", + }, { + name: "success_idna", + in: "пример.рф", + wantErrAs: nil, + wantErrMsg: "", + }, { + name: "bad_idna", + in: "xn---.com", + wantErrAs: nil, + wantErrMsg: `bad hostname "xn---.com": idna: invalid label "-"`, + }, { + name: "success_one", + in: "e", + wantErrAs: nil, + wantErrMsg: "", + }, { + name: "empty", + in: "", + wantErrAs: new(errors.Error), + wantErrMsg: `bad hostname "": address is empty`, + }, { + name: "bad_symbol", + in: "!!!", + wantErrAs: new(*netutil.RuneError), + wantErrMsg: `bad hostname "!!!": ` + + `bad top-level domain name label "!!!": ` + + `bad top-level domain name label rune '!'`, + }, { + name: "bad_length", + in: longDomainName, + wantErrAs: new(*netutil.LengthError), + wantErrMsg: `bad hostname "` + longDomainName + `": ` + + `hostname is too long: got 255, max 253`, + }, { + name: "bad_label_length", + in: longLabelDomainName, + wantErrAs: new(*netutil.LengthError), + wantErrMsg: `bad hostname "` + longLabelDomainName + `": ` + + `bad hostname label "` + longLabel + `": ` + + `hostname label is too long: got 64, max 63`, + }, { + name: "bad_label_empty", + in: "example..com", + wantErrAs: new(errors.Error), + wantErrMsg: `bad hostname "example..com": ` + + `bad hostname label "": label is empty`, }, { name: "bad_label_first_symbol", in: "example.-aa.com", wantErrAs: new(*netutil.RuneError), - wantErrMsg: `bad domain name "example.-aa.com": ` + - `bad domain name label "-aa": bad domain name label rune '-'`, + wantErrMsg: `bad hostname "example.-aa.com": ` + + `bad hostname label "-aa": bad hostname label rune '-'`, }, { name: "bad_label_last_symbol", in: "example-.aa.com", wantErrAs: new(*netutil.RuneError), - wantErrMsg: `bad domain name "example-.aa.com": ` + - `bad domain name label "example-": bad domain name label rune '-'`, + wantErrMsg: `bad hostname "example-.aa.com": ` + + `bad hostname label "example-": bad hostname label rune '-'`, }, { name: "bad_label_symbol", in: "example.a!!!.com", wantErrAs: new(*netutil.RuneError), - wantErrMsg: `bad domain name "example.a!!!.com": ` + - `bad domain name label "a!!!": bad domain name label rune '!'`, + wantErrMsg: `bad hostname "example.a!!!.com": ` + + `bad hostname label "a!!!": bad hostname label rune '!'`, + }, { + name: "numeric_tld", + in: "example.123", + wantErrAs: new(*netutil.LabelError), + wantErrMsg: `bad hostname "example.123": ` + + `bad top-level domain name label "123": all octets are numeric`, }} for _, tc := range testCases { @@ -269,7 +379,7 @@ func TestValidateDomainName(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - err := netutil.ValidateDomainName(tc.in) + err := netutil.ValidateHostname(tc.in) testutil.AssertErrorMsg(t, tc.wantErrMsg, err) if tc.wantErrAs != nil { @@ -312,7 +422,7 @@ func TestValidateSRVDomainName(t *testing.T) { `idna: invalid label "-"`, }, { name: "success_one", - in: "_u", + in: "_u.tld", wantErrAs: nil, wantErrMsg: "", }, { @@ -325,7 +435,8 @@ func TestValidateSRVDomainName(t *testing.T) { in: "_!", wantErrAs: new(*netutil.RuneError), wantErrMsg: `bad service domain name "_!": ` + - `bad service name label "_!": bad service name label rune '!'`, + `bad top-level domain name label "_!": ` + + `bad top-level domain name label rune '_'`, }, { name: "bad_length", in: longDomainName, @@ -344,7 +455,7 @@ func TestValidateSRVDomainName(t *testing.T) { in: "example..com", wantErrAs: new(errors.Error), wantErrMsg: `bad service domain name "example..com": ` + - `bad domain name label "": label is empty`, + `bad hostname label "": label is empty`, }, { name: "bad_label_first_symbol", in: "example._-a.com", @@ -369,6 +480,12 @@ func TestValidateSRVDomainName(t *testing.T) { wantErrAs: new(*netutil.AddrError), wantErrMsg: `bad service domain name "example._.com": ` + `bad service name label "_": label is empty`, + }, { + name: "bad_hostname_label", + in: "-srv.com", + wantErrAs: new(*netutil.AddrError), + wantErrMsg: `bad service domain name "-srv.com": ` + + `bad hostname label "-srv": bad hostname label rune '-'`, }} for _, tc := range testCases { @@ -376,10 +493,6 @@ func TestValidateSRVDomainName(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - if tc.name == "bad_label_empty" { - assert.True(t, true) - } - err := netutil.ValidateSRVDomainName(tc.in) testutil.AssertErrorMsg(t, tc.wantErrMsg, err) @@ -408,7 +521,7 @@ func TestValidateServiceNameLabel_errors(t *testing.T) { in: "non-service.com", name: "bad_rune", }, { - wantErrAs: new(*netutil.AddrError), + wantErrAs: new(*netutil.LabelError), wantErrMsg: `bad service name label "": label is empty`, in: "", name: "empty", @@ -422,10 +535,8 @@ func TestValidateServiceNameLabel_errors(t *testing.T) { err := netutil.ValidateServiceNameLabel(tc.in) testutil.AssertErrorMsg(t, tc.wantErrMsg, err) - assert.ErrorAs(t, err, new(*netutil.AddrError)) - if tc.wantErrAs != nil { - assert.ErrorAs(t, err, tc.wantErrAs) - } + assert.ErrorAs(t, err, new(*netutil.LabelError)) + assert.ErrorAs(t, err, tc.wantErrAs) }) } } diff --git a/netutil/error.go b/netutil/error.go index 91671d7..67ad370 100644 --- a/netutil/error.go +++ b/netutil/error.go @@ -29,22 +29,22 @@ const ( ErrNotAReversedSubnet errors.Error = "not a reversed ip network" ) -// AddrKind is the kind of address or address part used for error reporting. -type AddrKind string +// AddrKind is a convenient alias for string describing the kind of address and +// used for error reporting. +type AddrKind = string -// Kinds of addresses for AddrError. +// Kinds of addresses for [AddrError]. const ( - AddrKindARPA AddrKind = "arpa domain name" - AddrKindCIDR AddrKind = "cidr address" - AddrKindHostPort AddrKind = "hostport address" - AddrKindIP AddrKind = "ip address" - AddrKindIPPort AddrKind = "ipport address" - AddrKindIPv4 AddrKind = "ipv4 address" - AddrKindLabel AddrKind = "domain name label" - AddrKindSRVLabel AddrKind = "service name label" - AddrKindMAC AddrKind = "mac address" - AddrKindName AddrKind = "domain name" - AddrKindSRVName AddrKind = "service domain name" + AddrKindARPA AddrKind = "arpa domain name" + AddrKindCIDR AddrKind = "cidr address" + AddrKindHostPort AddrKind = "hostport address" + AddrKindIP AddrKind = "ip address" + AddrKindIPPort AddrKind = "ipport address" + AddrKindIPv4 AddrKind = "ipv4 address" + AddrKindMAC AddrKind = "mac address" + AddrKindName AddrKind = "hostname" + AddrKindDomainName AddrKind = "domain name" + AddrKindSRVName AddrKind = "service domain name" ) // AddrError is the underlying type of errors returned from validation @@ -98,11 +98,75 @@ func makeAddrError(errPtr *error, addr string, k AddrKind) { } } +// LabelKind is a convenient alias for string describing the kind of label of a +// name and used for error reporting. +type LabelKind = string + +// Kinds of labels for [LabelError]. +const ( + LabelKindDomain LabelKind = "domain name label" + LabelKindHost LabelKind = "hostname label" + LabelKindSRV LabelKind = "service name label" + LabelKindTLD LabelKind = "top-level domain name label" +) + +// LabelError is the underlying type of errors returned from validation +// functions when a label of a name is invalid. +type LabelError struct { + // Err is the underlying error, if any. + Err error + + // Kind is the kind of label of the name. + Kind LabelKind + + // Label is the text of the invalid label. + Label string +} + +// type check +var _ error = (*AddrError)(nil) + +// Error implements the error interface for *AddrError. +func (err *LabelError) Error() (msg string) { + if err.Err != nil { + return fmt.Sprintf("bad %s %q: %s", err.Kind, err.Label, err.Err) + } + + return fmt.Sprintf("bad %s %q", err.Kind, err.Label) +} + +// type check +var _ errors.Wrapper = (*AddrError)(nil) + +// Unwrap implements the [errors.Wrapper] interface for *AddrError. It returns +// err.Err. +func (err *LabelError) Unwrap() (unwrapped error) { + return err.Err +} + +// makeLabelError is a deferrable helper for functions that return +// [*LabelError]. errPtr must be non-nil. Usage example: +// +// defer makeLabelError(&err, label, LabelKindDomain) +func makeLabelError(errPtr *error, label string, k LabelKind) { + err := *errPtr + if err == nil { + return + } + + *errPtr = &LabelError{ + Err: err, + Kind: k, + Label: label, + } +} + // LengthError is the underlying type of errors returned from validation -// functions when an address or a part of an address has a bad length. +// functions when an address or a part of an address has a bad length. Kind is +// either [AddrKind] or [LabelKind]. type LengthError struct { // Kind is the kind of address or address part. - Kind AddrKind + Kind string // Allowed are the allowed lengths for this kind of address. If allowed // is empty, Max should be non-zero. @@ -131,10 +195,11 @@ func (err *LengthError) Error() (msg string) { } // RuneError is the underlying type of errors returned from validation functions -// when a rune in the address is invalid. +// when a rune in the address is invalid. Kind is either [AddrKind] or +// [LabelKind]. type RuneError struct { // Kind is the kind of address or address part. - Kind AddrKind + Kind string // Rune is the invalid rune. Rune rune @@ -144,3 +209,20 @@ type RuneError struct { func (err *RuneError) Error() (msg string) { return fmt.Sprintf("bad %s rune %q", err.Kind, err.Rune) } + +// replaceKind replaces the Kind field of err with newKind. err must be of type +// [*LabelError], [*AddrError], [*LengthError], or [*RuneError]. +func replaceKind(err error, newKind string) { + switch err := err.(type) { + case *LabelError: + err.Kind = newKind + case *AddrError: + err.Kind = newKind + case *LengthError: + err.Kind = newKind + case *RuneError: + err.Kind = newKind + default: + panic(fmt.Errorf("unexpected error type %T", err)) + } +} diff --git a/netutil/reversed.go b/netutil/reversed.go index 6b791a5..edf6066 100644 --- a/netutil/reversed.go +++ b/netutil/reversed.go @@ -108,10 +108,9 @@ func IPFromReversedAddr(arpa string) (ip net.IP, err error) { arpa = strings.TrimSuffix(arpa, ".") err = ValidateDomainName(arpa) if err != nil { - bdErr := err.(*AddrError) - bdErr.Kind = AddrKindARPA + replaceKind(err, AddrKindARPA) - return nil, bdErr + return nil, err } defer makeAddrError(&err, arpa, AddrKindARPA) @@ -221,7 +220,7 @@ func ipv4NetFromReversed(arpa string) (subnet *net.IPNet, err error) { // See RFC 1035 Section 3.5. return nil, &AddrError{ Err: errors.Error("leading zero is forbidden at this position"), - Kind: AddrKindLabel, + Kind: LabelKindDomain, Addr: addr[octetIdx:], } } @@ -336,10 +335,9 @@ func SubnetFromReversedAddr(arpa string) (subnet *net.IPNet, err error) { arpa = strings.TrimSuffix(arpa, ".") err = ValidateDomainName(arpa) if err != nil { - bdErr := err.(*AddrError) - bdErr.Kind = AddrKindARPA + replaceKind(err, AddrKindARPA) - return nil, bdErr + return nil, err } defer makeAddrError(&err, arpa, AddrKindARPA) diff --git a/netutil/reversed_test.go b/netutil/reversed_test.go index 837fbdc..06cadf1 100644 --- a/netutil/reversed_test.go +++ b/netutil/reversed_test.go @@ -153,14 +153,14 @@ func TestIPFromReversedAddr(t *testing.T) { name: "bad_ipv6_space", in: ipv6RevSpace, wantErrMsg: `bad arpa domain name "` + ipv6RevSpace + `": ` + - `bad domain name label " ": bad domain name label rune ' '`, + `bad arpa domain name rune ' '`, wantErrAs: new(*netutil.RuneError), want: nil, }, { name: "not_a_reversed_ip", in: testIPv4.String(), wantErrMsg: `bad arpa domain name "` + testIPv4.String() + `": ` + - `not a full reversed ip address`, + `bad top-level domain name label "4": all octets are numeric`, wantErrAs: new(errors.Error), want: nil, }} @@ -435,7 +435,7 @@ func TestSubnetFromReversedAddr(t *testing.T) { want: nil, wantErrAs: new(*netutil.RuneError), wantErrMsg: `bad arpa domain name "` + ipv6RevSpace + `": ` + - `bad domain name label " ": bad domain name label rune ' '`, + `bad arpa domain name rune ' '`, in: ipv6RevSpace, name: "bad_ipv6_space", }, { @@ -449,7 +449,7 @@ func TestSubnetFromReversedAddr(t *testing.T) { want: nil, wantErrAs: new(errors.Error), wantErrMsg: `bad arpa domain name "` + testIPv4.String() + `": ` + - `not a reversed ip network`, + `bad top-level domain name label "4": all octets are numeric`, in: testIPv4.String(), name: "not_a_reversed_subnet", }, {