@@ -15,6 +15,7 @@ package net
15
15
import (
16
16
"context"
17
17
"errors"
18
+ "internal/bytealg"
18
19
"io"
19
20
"time"
20
21
@@ -198,7 +199,9 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
198
199
199
200
// checkHeader performs basic sanity checks on the header.
200
201
func checkHeader (p * dnsmessage.Parser , h dnsmessage.Header ) error {
201
- if h .RCode == dnsmessage .RCodeNameError {
202
+ rcode := extractExtendedRCode (* p , h )
203
+
204
+ if rcode == dnsmessage .RCodeNameError {
202
205
return errNoSuchHost
203
206
}
204
207
@@ -209,17 +212,17 @@ func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header) error {
209
212
210
213
// libresolv continues to the next server when it receives
211
214
// an invalid referral response. See golang.org/issue/15434.
212
- if h . RCode == dnsmessage .RCodeSuccess && ! h .Authoritative && ! h .RecursionAvailable && err == dnsmessage .ErrSectionDone {
215
+ if rcode == dnsmessage .RCodeSuccess && ! h .Authoritative && ! h .RecursionAvailable && err == dnsmessage .ErrSectionDone {
213
216
return errLameReferral
214
217
}
215
218
216
- if h . RCode != dnsmessage .RCodeSuccess && h . RCode != dnsmessage .RCodeNameError {
219
+ if rcode != dnsmessage .RCodeSuccess && rcode != dnsmessage .RCodeNameError {
217
220
// None of the error codes make sense
218
221
// for the query we sent. If we didn't get
219
222
// a name error and we didn't get success,
220
223
// the server is behaving incorrectly or
221
224
// having temporary trouble.
222
- if h . RCode == dnsmessage .RCodeServerFailure {
225
+ if rcode == dnsmessage .RCodeServerFailure {
223
226
return errServerTemporarilyMisbehaving
224
227
}
225
228
return errServerMisbehaving
@@ -246,6 +249,23 @@ func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type) error {
246
249
}
247
250
}
248
251
252
+ // extractExtendedRCode extracts the extended RCode from the OPT resource (EDNS(0))
253
+ // If an OPT record is not found, the RCode from the hdr is returned.
254
+ func extractExtendedRCode (p dnsmessage.Parser , hdr dnsmessage.Header ) dnsmessage.RCode {
255
+ p .SkipAllAnswers ()
256
+ p .SkipAllAuthorities ()
257
+ for {
258
+ ahdr , err := p .AdditionalHeader ()
259
+ if err != nil {
260
+ return hdr .RCode
261
+ }
262
+ if ahdr .Type == dnsmessage .TypeOPT {
263
+ return ahdr .ExtendedRCode (hdr .RCode )
264
+ }
265
+ p .SkipAdditional ()
266
+ }
267
+ }
268
+
249
269
// Do a lookup for a single name, which must be rooted
250
270
// (otherwise answer will not find the answers).
251
271
func (r * Resolver ) tryOneName (ctx context.Context , cfg * dnsConfig , name string , qtype dnsmessage.Type ) (dnsmessage.Parser , string , error ) {
@@ -385,10 +405,6 @@ func avoidDNS(name string) bool {
385
405
386
406
// nameList returns a list of names for sequential DNS queries.
387
407
func (conf * dnsConfig ) nameList (name string ) []string {
388
- if avoidDNS (name ) {
389
- return nil
390
- }
391
-
392
408
// Check name length (see isDomainName).
393
409
l := len (name )
394
410
rooted := l > 0 && name [l - 1 ] == '.'
@@ -398,27 +414,31 @@ func (conf *dnsConfig) nameList(name string) []string {
398
414
399
415
// If name is rooted (trailing dot), try only that name.
400
416
if rooted {
417
+ if avoidDNS (name ) {
418
+ return nil
419
+ }
401
420
return []string {name }
402
421
}
403
422
404
- hasNdots := count (name , '.' ) >= conf .ndots
423
+ hasNdots := bytealg . CountString (name , '.' ) >= conf .ndots
405
424
name += "."
406
425
l ++
407
426
408
427
// Build list of search choices.
409
428
names := make ([]string , 0 , 1 + len (conf .search ))
410
429
// If name has enough dots, try unsuffixed first.
411
- if hasNdots {
430
+ if hasNdots && ! avoidDNS ( name ) {
412
431
names = append (names , name )
413
432
}
414
433
// Try suffixes that are not too long (see isDomainName).
415
434
for _ , suffix := range conf .search {
416
- if l + len (suffix ) <= 254 {
417
- names = append (names , name + suffix )
435
+ fqdn := name + suffix
436
+ if ! avoidDNS (fqdn ) && len (fqdn ) <= 254 {
437
+ names = append (names , fqdn )
418
438
}
419
439
}
420
440
// Try unsuffixed, if not tried first above.
421
- if ! hasNdots {
441
+ if ! hasNdots && ! avoidDNS ( name ) {
422
442
names = append (names , name )
423
443
}
424
444
return names
@@ -520,7 +540,7 @@ func (r *Resolver) goLookupIPCNAME(ctx context.Context, network, name string, co
520
540
h , err := result .p .AnswerHeader ()
521
541
if err != nil && err != dnsmessage .ErrSectionDone {
522
542
lastErr = & DNSError {
523
- Err : "cannot marshal DNS message" ,
543
+ Err : errCannotUnmarshalDNSMessage . Error () ,
524
544
Name : name ,
525
545
Server : result .server ,
526
546
}
@@ -533,7 +553,7 @@ func (r *Resolver) goLookupIPCNAME(ctx context.Context, network, name string, co
533
553
a , err := result .p .AResource ()
534
554
if err != nil {
535
555
lastErr = & DNSError {
536
- Err : "cannot marshal DNS message" ,
556
+ Err : errCannotUnmarshalDNSMessage . Error () ,
537
557
Name : name ,
538
558
Server : result .server ,
539
559
}
@@ -548,7 +568,7 @@ func (r *Resolver) goLookupIPCNAME(ctx context.Context, network, name string, co
548
568
aaaa , err := result .p .AAAAResource ()
549
569
if err != nil {
550
570
lastErr = & DNSError {
551
- Err : "cannot marshal DNS message" ,
571
+ Err : errCannotUnmarshalDNSMessage . Error () ,
552
572
Name : name ,
553
573
Server : result .server ,
554
574
}
@@ -563,7 +583,7 @@ func (r *Resolver) goLookupIPCNAME(ctx context.Context, network, name string, co
563
583
c , err := result .p .CNAMEResource ()
564
584
if err != nil {
565
585
lastErr = & DNSError {
566
- Err : "cannot marshal DNS message" ,
586
+ Err : errCannotUnmarshalDNSMessage . Error () ,
567
587
Name : name ,
568
588
Server : result .server ,
569
589
}
@@ -576,7 +596,7 @@ func (r *Resolver) goLookupIPCNAME(ctx context.Context, network, name string, co
576
596
default :
577
597
if err := result .p .SkipAnswer (); err != nil {
578
598
lastErr = & DNSError {
579
- Err : "cannot marshal DNS message" ,
599
+ Err : errCannotUnmarshalDNSMessage . Error () ,
580
600
Name : name ,
581
601
Server : result .server ,
582
602
}
@@ -612,16 +632,14 @@ func (r *Resolver) goLookupIPCNAME(ctx context.Context, network, name string, co
612
632
return addrs , cname , nil
613
633
}
614
634
635
+ // goLookupCNAME is the native Go (non-cgo) implementation of LookupCNAME.
636
+ func (r * Resolver ) goLookupCNAME (ctx context.Context , host string , conf * dnsConfig ) (string , error ) {
637
+ _ , cname , err := r .goLookupIPCNAME (ctx , "CNAME" , host , conf )
638
+ return cname .String (), err
639
+ }
640
+
615
641
// goLookupPTR is the native Go implementation of LookupAddr.
616
- // Used only if cgoLookupPTR refuses to handle the request (that is,
617
- // only if cgoLookupPTR is the stub in cgo_stub.go).
618
- // Normally we let cgo use the C library resolver instead of depending
619
- // on our lookup code, so that Go and C get the same answers.
620
642
func (r * Resolver ) goLookupPTR (ctx context.Context , addr string , conf * dnsConfig ) ([]string , error ) {
621
- names := lookupStaticAddr (addr )
622
- if len (names ) > 0 {
623
- return names , nil
624
- }
625
643
arpa , err := reverseaddr (addr )
626
644
if err != nil {
627
645
return nil , err
@@ -638,7 +656,7 @@ func (r *Resolver) goLookupPTR(ctx context.Context, addr string, conf *dnsConfig
638
656
}
639
657
if err != nil {
640
658
return nil , & DNSError {
641
- Err : "cannot marshal DNS message" ,
659
+ Err : errCannotUnmarshalDNSMessage . Error () ,
642
660
Name : addr ,
643
661
Server : server ,
644
662
}
@@ -647,7 +665,7 @@ func (r *Resolver) goLookupPTR(ctx context.Context, addr string, conf *dnsConfig
647
665
err := p .SkipAnswer ()
648
666
if err != nil {
649
667
return nil , & DNSError {
650
- Err : "cannot marshal DNS message" ,
668
+ Err : errCannotUnmarshalDNSMessage . Error () ,
651
669
Name : addr ,
652
670
Server : server ,
653
671
}
@@ -657,7 +675,7 @@ func (r *Resolver) goLookupPTR(ctx context.Context, addr string, conf *dnsConfig
657
675
ptr , err := p .PTRResource ()
658
676
if err != nil {
659
677
return nil , & DNSError {
660
- Err : "cannot marshal DNS message" ,
678
+ Err : errCannotUnmarshalDNSMessage . Error () ,
661
679
Name : addr ,
662
680
Server : server ,
663
681
}
0 commit comments