Search in sources :

Example 1 with DnsRecordType

use of io.netty.handler.codec.dns.DnsRecordType in project netty by netty.

the class DnsNameResolverContext method onResponseAorAAAA.

private void onResponseAorAAAA(DnsRecordType qType, DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope, Promise<T> promise) {
    // We often get a bunch of CNAMES as well when we asked for A/AAAA.
    final DnsResponse response = envelope.content();
    final Map<String, String> cnames = buildAliasMap(response);
    final int answerCount = response.count(DnsSection.ANSWER);
    boolean found = false;
    for (int i = 0; i < answerCount; i++) {
        final DnsRecord r = response.recordAt(DnsSection.ANSWER, i);
        final DnsRecordType type = r.type();
        if (type != DnsRecordType.A && type != DnsRecordType.AAAA) {
            continue;
        }
        final String questionName = question.name().toLowerCase(Locale.US);
        final String recordName = r.name().toLowerCase(Locale.US);
        // Make sure the record is for the questioned domain.
        if (!recordName.equals(questionName)) {
            // Even if the record's name is not exactly same, it might be an alias defined in the CNAME records.
            String resolved = questionName;
            do {
                resolved = cnames.get(resolved);
                if (recordName.equals(resolved)) {
                    break;
                }
            } while (resolved != null);
            if (resolved == null) {
                continue;
            }
        }
        InetAddress resolved = parseAddress(r, hostname);
        if (resolved == null) {
            continue;
        }
        if (resolvedEntries == null) {
            resolvedEntries = new ArrayList<DnsCacheEntry>(8);
        }
        final DnsCacheEntry e = new DnsCacheEntry(hostname, resolved);
        resolveCache.cache(hostname, additionals, resolved, r.timeToLive(), parent.ch.eventLoop());
        resolvedEntries.add(e);
        found = true;
    // Note that we do not break from the loop here, so we decode/cache all A/AAAA records.
    }
    if (found) {
        return;
    }
    if (traceEnabled) {
        addTrace(envelope.sender(), "no matching " + qType + " record found");
    }
    // We aked for A/AAAA but we got only CNAME.
    if (!cnames.isEmpty()) {
        onResponseCNAME(question, envelope, cnames, false, promise);
    }
}
Also used : DnsResponse(io.netty.handler.codec.dns.DnsResponse) DnsRecordType(io.netty.handler.codec.dns.DnsRecordType) DnsRecord(io.netty.handler.codec.dns.DnsRecord) InetAddress(java.net.InetAddress)

Example 2 with DnsRecordType

use of io.netty.handler.codec.dns.DnsRecordType in project netty by netty.

the class DnsNameResolverContext method onResponse.

void onResponse(final DnsServerAddressStream nameServerAddrStream, final DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope, Promise<T> promise) {
    try {
        final DnsResponse res = envelope.content();
        final DnsResponseCode code = res.code();
        if (code == DnsResponseCode.NOERROR) {
            if (handleRedirect(question, envelope, promise)) {
                // Was a redirect so return here as everything else is handled in handleRedirect(...)
                return;
            }
            final DnsRecordType type = question.type();
            if (type == DnsRecordType.A || type == DnsRecordType.AAAA) {
                onResponseAorAAAA(type, question, envelope, promise);
            } else if (type == DnsRecordType.CNAME) {
                onResponseCNAME(question, envelope, promise);
            }
            return;
        }
        if (traceEnabled) {
            addTrace(envelope.sender(), "response code: " + code + " with " + res.count(DnsSection.ANSWER) + " answer(s) and " + res.count(DnsSection.AUTHORITY) + " authority resource(s)");
        }
        // Retry with the next server if the server did not tell us that the domain does not exist.
        if (code != DnsResponseCode.NXDOMAIN) {
            query(nameServerAddrStream, question, promise);
        }
    } finally {
        ReferenceCountUtil.safeRelease(envelope);
    }
}
Also used : DnsResponse(io.netty.handler.codec.dns.DnsResponse) DnsResponseCode(io.netty.handler.codec.dns.DnsResponseCode) DnsRecordType(io.netty.handler.codec.dns.DnsRecordType)

Example 3 with DnsRecordType

use of io.netty.handler.codec.dns.DnsRecordType in project netty by netty.

the class DnsNameResolver method resolveAll.

private Future<List<DnsRecord>> resolveAll(DnsQuestion question, DnsRecord[] additionals, Promise<List<DnsRecord>> promise) {
    checkNotNull(question, "question");
    checkNotNull(promise, "promise");
    // Respect /etc/hosts as well if the record type is A or AAAA.
    final DnsRecordType type = question.type();
    final String hostname = question.name();
    if (type == DnsRecordType.A || type == DnsRecordType.AAAA) {
        final List<InetAddress> hostsFileEntries = resolveHostsFileEntries(hostname);
        if (hostsFileEntries != null) {
            List<DnsRecord> result = new ArrayList<DnsRecord>();
            for (InetAddress hostsFileEntry : hostsFileEntries) {
                ByteBuf content = null;
                if (hostsFileEntry instanceof Inet4Address) {
                    if (type == DnsRecordType.A) {
                        content = Unpooled.wrappedBuffer(hostsFileEntry.getAddress());
                    }
                } else if (hostsFileEntry instanceof Inet6Address) {
                    if (type == DnsRecordType.AAAA) {
                        content = Unpooled.wrappedBuffer(hostsFileEntry.getAddress());
                    }
                }
                if (content != null) {
                    // Our current implementation does not support reloading the hosts file,
                    // so use a fairly large TTL (1 day, i.e. 86400 seconds).
                    result.add(new DefaultDnsRawRecord(hostname, type, 86400, content));
                }
            }
            if (!result.isEmpty()) {
                trySuccess(promise, result);
                return promise;
            }
        }
    }
    // It was not A/AAAA question or there was no entry in /etc/hosts.
    final DnsServerAddressStream nameServerAddrs = dnsServerAddressStreamProvider.nameServerAddressStream(hostname);
    new DnsRecordResolveContext(this, promise, question, additionals, nameServerAddrs, maxQueriesPerResolve).resolve(promise);
    return promise;
}
Also used : Inet4Address(java.net.Inet4Address) ArrayList(java.util.ArrayList) DnsRecordType(io.netty.handler.codec.dns.DnsRecordType) Inet6Address(java.net.Inet6Address) ByteBuf(io.netty.buffer.ByteBuf) DefaultDnsRawRecord(io.netty.handler.codec.dns.DefaultDnsRawRecord) DnsRecord(io.netty.handler.codec.dns.DnsRecord) InetAddress(java.net.InetAddress)

Example 4 with DnsRecordType

use of io.netty.handler.codec.dns.DnsRecordType in project netty by netty.

the class DnsResolveContext method onExpectedResponse.

private void onExpectedResponse(DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope, final DnsQueryLifecycleObserver queryLifecycleObserver, Promise<List<T>> promise) {
    // We often get a bunch of CNAMES as well when we asked for A/AAAA.
    final DnsResponse response = envelope.content();
    final Map<String, String> cnames = buildAliasMap(response, cnameCache(), parent.executor());
    final int answerCount = response.count(DnsSection.ANSWER);
    boolean found = false;
    boolean completeEarly = this.completeEarly;
    for (int i = 0; i < answerCount; i++) {
        final DnsRecord r = response.recordAt(DnsSection.ANSWER, i);
        final DnsRecordType type = r.type();
        boolean matches = false;
        for (DnsRecordType expectedType : expectedTypes) {
            if (type == expectedType) {
                matches = true;
                break;
            }
        }
        if (!matches) {
            continue;
        }
        final String questionName = question.name().toLowerCase(Locale.US);
        final String recordName = r.name().toLowerCase(Locale.US);
        // Make sure the record is for the questioned domain.
        if (!recordName.equals(questionName)) {
            Map<String, String> cnamesCopy = new HashMap<String, String>(cnames);
            // Even if the record's name is not exactly same, it might be an alias defined in the CNAME records.
            String resolved = questionName;
            do {
                resolved = cnamesCopy.remove(resolved);
                if (recordName.equals(resolved)) {
                    break;
                }
            } while (resolved != null);
            if (resolved == null) {
                assert questionName.isEmpty() || questionName.charAt(questionName.length() - 1) == '.';
                for (String searchDomain : parent.searchDomains()) {
                    if (searchDomain.isEmpty()) {
                        continue;
                    }
                    final String fqdn;
                    if (searchDomain.charAt(searchDomain.length() - 1) == '.') {
                        fqdn = questionName + searchDomain;
                    } else {
                        fqdn = questionName + searchDomain + '.';
                    }
                    if (recordName.equals(fqdn)) {
                        resolved = recordName;
                        break;
                    }
                }
                if (resolved == null) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Ignoring record {} as it contains a different name than the " + "question name [{}]. Cnames: {}, Search domains: {}", r.toString(), questionName, cnames, parent.searchDomains());
                    }
                    continue;
                }
            }
        }
        final T converted = convertRecord(r, hostname, additionals, parent.executor());
        if (converted == null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Ignoring record {} as the converted record is null. hostname [{}], Additionals: {}", r.toString(), hostname, additionals);
            }
            continue;
        }
        boolean shouldRelease = false;
        // include the result
        if (!completeEarly) {
            completeEarly = isCompleteEarly(converted);
        }
        // for the extra memory copy and allocations in this cases later on.
        if (finalResult == null) {
            finalResult = new ArrayList<T>(8);
            finalResult.add(converted);
        } else if (isDuplicateAllowed() || !finalResult.contains(converted)) {
            finalResult.add(converted);
        } else {
            shouldRelease = true;
        }
        cache(hostname, additionals, r, converted);
        found = true;
        if (shouldRelease) {
            ReferenceCountUtil.release(converted);
        }
    // Note that we do not break from the loop here, so we decode/cache all A/AAAA records.
    }
    if (cnames.isEmpty()) {
        if (found) {
            if (completeEarly) {
                this.completeEarly = true;
            }
            queryLifecycleObserver.querySucceed();
            return;
        }
        queryLifecycleObserver.queryFailed(NO_MATCHING_RECORD_QUERY_FAILED_EXCEPTION);
    } else {
        queryLifecycleObserver.querySucceed();
        // We also got a CNAME so we need to ensure we also query it.
        onResponseCNAME(question, cnames, newDnsQueryLifecycleObserver(question), promise);
    }
}
Also used : HashMap(java.util.HashMap) IdentityHashMap(java.util.IdentityHashMap) DnsResponse(io.netty.handler.codec.dns.DnsResponse) DnsRecordType(io.netty.handler.codec.dns.DnsRecordType) DnsRecord(io.netty.handler.codec.dns.DnsRecord)

Example 5 with DnsRecordType

use of io.netty.handler.codec.dns.DnsRecordType in project netty by netty.

the class DnsResolveContext method buildAliasMap.

private static Map<String, String> buildAliasMap(DnsResponse response, DnsCnameCache cache, EventLoop loop) {
    final int answerCount = response.count(DnsSection.ANSWER);
    Map<String, String> cnames = null;
    for (int i = 0; i < answerCount; i++) {
        final DnsRecord r = response.recordAt(DnsSection.ANSWER, i);
        final DnsRecordType type = r.type();
        if (type != DnsRecordType.CNAME) {
            continue;
        }
        if (!(r instanceof DnsRawRecord)) {
            continue;
        }
        final ByteBuf recordContent = ((ByteBufHolder) r).content();
        final String domainName = decodeDomainName(recordContent);
        if (domainName == null) {
            continue;
        }
        if (cnames == null) {
            cnames = new HashMap<String, String>(min(8, answerCount));
        }
        String name = r.name().toLowerCase(Locale.US);
        String mapping = domainName.toLowerCase(Locale.US);
        // Cache the CNAME as well.
        String nameWithDot = hostnameWithDot(name);
        String mappingWithDot = hostnameWithDot(mapping);
        if (!nameWithDot.equalsIgnoreCase(mappingWithDot)) {
            cache.cache(nameWithDot, mappingWithDot, r.timeToLive(), loop);
            cnames.put(name, mapping);
        }
    }
    return cnames != null ? cnames : Collections.<String, String>emptyMap();
}
Also used : DnsRawRecord(io.netty.handler.codec.dns.DnsRawRecord) ByteBufHolder(io.netty.buffer.ByteBufHolder) DnsRecordType(io.netty.handler.codec.dns.DnsRecordType) DnsRecord(io.netty.handler.codec.dns.DnsRecord) ByteBuf(io.netty.buffer.ByteBuf)

Aggregations

DnsRecordType (io.netty.handler.codec.dns.DnsRecordType)9 DnsRecord (io.netty.handler.codec.dns.DnsRecord)7 DnsResponse (io.netty.handler.codec.dns.DnsResponse)5 ByteBuf (io.netty.buffer.ByteBuf)3 ByteBufHolder (io.netty.buffer.ByteBufHolder)2 DnsRawRecord (io.netty.handler.codec.dns.DnsRawRecord)2 DnsResponseCode (io.netty.handler.codec.dns.DnsResponseCode)2 InetAddress (java.net.InetAddress)2 UnknownHostException (java.net.UnknownHostException)2 ArrayList (java.util.ArrayList)2 ChannelFuture (io.netty.channel.ChannelFuture)1 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)1 DecoderException (io.netty.handler.codec.DecoderException)1 DatagramDnsQuery (io.netty.handler.codec.dns.DatagramDnsQuery)1 DefaultDnsQuestion (io.netty.handler.codec.dns.DefaultDnsQuestion)1 DefaultDnsRawRecord (io.netty.handler.codec.dns.DefaultDnsRawRecord)1 DnsException (io.vertx.core.dns.DnsException)1 DnsResponseCode (io.vertx.core.dns.DnsResponseCode)1 Inet4Address (java.net.Inet4Address)1 Inet6Address (java.net.Inet6Address)1