@ -598,8 +598,18 @@ func (f *forwarder) forwardWithDestChan(ctx context.Context, query packet, respo
// out, playing on Sonos still works.
if hasRDNSBonjourPrefix ( domain ) {
metricDNSFwdDropBonjour . Add ( 1 )
res , err := nxDomainResponse ( query )
if err != nil {
f . logf ( "error parsing bonjour query: %v" , err )
return nil
}
select {
case <- ctx . Done ( ) :
return ctx . Err ( )
case responseChan <- res :
return nil
}
}
clampEDNSSize ( query . bs , maxResponseBytes )
@ -696,6 +706,28 @@ func nameFromQuery(bs []byte) (dnsname.FQDN, error) {
return dnsname . ToFQDN ( rawNameToLower ( n ) )
}
// nxDomainResponse returns an NXDomain DNS reply for the provided request.
func nxDomainResponse ( req packet ) ( res packet , err error ) {
p := dnsParserPool . Get ( ) . ( * dnsParser )
defer dnsParserPool . Put ( p )
if err := p . parseQuery ( req . bs ) ; err != nil {
return packet { } , err
}
h := p . Header
h . Response = true
h . RecursionAvailable = h . RecursionDesired
h . RCode = dns . RCodeNameError
b := dns . NewBuilder ( nil , h )
// TODO(bradfitz): should we add an SOA record in the Authority
// section too? (for the nxdomain negative caching TTL)
// For which zone? Does iOS care?
res . bs , err = b . Finish ( )
res . addr = req . addr
return res , err
}
// closePool is a dynamic set of io.Closers to close as a group.
// It's intended to be Closed at most once.
//