Search in sources :

Example 1 with DnsResponse

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

the class DnsNameResolverTest method testQueryMx.

@Test
public void testQueryMx() throws Exception {
    DnsNameResolver resolver = newResolver().build();
    try {
        assertThat(resolver.isRecursionDesired(), is(true));
        Map<String, Future<AddressedEnvelope<DnsResponse, InetSocketAddress>>> futures = new LinkedHashMap<String, Future<AddressedEnvelope<DnsResponse, InetSocketAddress>>>();
        for (String name : DOMAINS) {
            if (EXCLUSIONS_QUERY_MX.contains(name)) {
                continue;
            }
            queryMx(resolver, futures, name);
        }
        for (Entry<String, Future<AddressedEnvelope<DnsResponse, InetSocketAddress>>> e : futures.entrySet()) {
            String hostname = e.getKey();
            Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> f = e.getValue().awaitUninterruptibly();
            DnsResponse response = f.getNow().content();
            assertThat(response.code(), is(DnsResponseCode.NOERROR));
            final int answerCount = response.count(DnsSection.ANSWER);
            final List<DnsRecord> mxList = new ArrayList<DnsRecord>(answerCount);
            for (int i = 0; i < answerCount; i++) {
                final DnsRecord r = response.recordAt(DnsSection.ANSWER, i);
                if (r.type() == DnsRecordType.MX) {
                    mxList.add(r);
                }
            }
            assertThat(mxList.size(), is(greaterThan(0)));
            StringBuilder buf = new StringBuilder();
            for (DnsRecord r : mxList) {
                ByteBuf recordContent = ((ByteBufHolder) r).content();
                buf.append(StringUtil.NEWLINE);
                buf.append('\t');
                buf.append(r.name());
                buf.append(' ');
                buf.append(r.type().name());
                buf.append(' ');
                buf.append(recordContent.readUnsignedShort());
                buf.append(' ');
                buf.append(DnsNameResolverContext.decodeDomainName(recordContent));
            }
            logger.info("{} has the following MX records:{}", hostname, buf);
            response.release();
        }
    } finally {
        resolver.close();
    }
}
Also used : AddressedEnvelope(io.netty.channel.AddressedEnvelope) InetSocketAddress(java.net.InetSocketAddress) ArrayList(java.util.ArrayList) ByteBuf(io.netty.buffer.ByteBuf) LinkedHashMap(java.util.LinkedHashMap) DnsResponse(io.netty.handler.codec.dns.DnsResponse) Future(io.netty.util.concurrent.Future) ByteBufHolder(io.netty.buffer.ByteBufHolder) DnsRecord(io.netty.handler.codec.dns.DnsRecord) Test(org.junit.Test)

Example 2 with DnsResponse

use of io.netty.handler.codec.dns.DnsResponse 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 3 with DnsResponse

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

the class DnsNameResolverContext method handleRedirect.

/**
     * Handle redirects if needed and returns {@code true} if there was a redirect handled. If {@code true} is returned
     * this method took ownership of the {@code promise} otherwise {@code false} is returned.
     */
private boolean handleRedirect(DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope, Promise<T> promise) {
    final DnsResponse res = envelope.content();
    // Check if we have answers, if not this may be an non authority NS and so redirects must be handled.
    if (res.count(DnsSection.ANSWER) == 0) {
        AuthoritativeNameServerList serverNames = extractAuthoritativeNameServers(question.name(), res);
        if (serverNames != null) {
            List<InetSocketAddress> nameServers = new ArrayList<InetSocketAddress>(serverNames.size());
            int additionalCount = res.count(DnsSection.ADDITIONAL);
            for (int i = 0; i < additionalCount; i++) {
                final DnsRecord r = res.recordAt(DnsSection.ADDITIONAL, i);
                if ((r.type() == DnsRecordType.A && !parent.supportsARecords()) || r.type() == DnsRecordType.AAAA && !parent.supportsAAAARecords()) {
                    continue;
                }
                final String recordName = r.name();
                AuthoritativeNameServer authoritativeNameServer = serverNames.remove(recordName);
                if (authoritativeNameServer == null) {
                    // Not a server we are interested in.
                    continue;
                }
                InetAddress resolved = parseAddress(r, recordName);
                if (resolved == null) {
                    // Could not parse it, move to the next.
                    continue;
                }
                nameServers.add(new InetSocketAddress(resolved, parent.dnsRedirectPort(resolved)));
                addNameServerToCache(authoritativeNameServer, resolved, r.timeToLive());
            }
            if (nameServers.isEmpty()) {
                promise.tryFailure(new UnknownHostException("Unable to find correct name server for " + hostname));
            } else {
                // Shuffle as we want to re-distribute the load across name servers.
                query(DnsServerAddresses.shuffled(nameServers).stream(), question, promise);
            }
            return true;
        }
    }
    return false;
}
Also used : UnknownHostException(java.net.UnknownHostException) InetSocketAddress(java.net.InetSocketAddress) DnsResponse(io.netty.handler.codec.dns.DnsResponse) ArrayList(java.util.ArrayList) DnsRecord(io.netty.handler.codec.dns.DnsRecord) InetAddress(java.net.InetAddress)

Example 4 with DnsResponse

use of io.netty.handler.codec.dns.DnsResponse 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 5 with DnsResponse

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

the class DnsQueryContext method finish.

void finish(AddressedEnvelope<? extends DnsResponse, InetSocketAddress> envelope) {
    final DnsResponse res = envelope.content();
    if (res.count(DnsSection.QUESTION) != 1) {
        logger.warn("Received a DNS response with invalid number of questions: {}", envelope);
        return;
    }
    if (!question().equals(res.recordAt(DnsSection.QUESTION))) {
        logger.warn("Received a mismatching DNS response: {}", envelope);
        return;
    }
    setSuccess(envelope);
}
Also used : DnsResponse(io.netty.handler.codec.dns.DnsResponse)

Aggregations

DnsResponse (io.netty.handler.codec.dns.DnsResponse)7 DnsRecord (io.netty.handler.codec.dns.DnsRecord)4 DnsRecordType (io.netty.handler.codec.dns.DnsRecordType)3 InetSocketAddress (java.net.InetSocketAddress)3 UnknownHostException (java.net.UnknownHostException)3 ArrayList (java.util.ArrayList)3 AddressedEnvelope (io.netty.channel.AddressedEnvelope)2 Future (io.netty.util.concurrent.Future)2 InetAddress (java.net.InetAddress)2 ByteBuf (io.netty.buffer.ByteBuf)1 ByteBufHolder (io.netty.buffer.ByteBufHolder)1 ChannelFuture (io.netty.channel.ChannelFuture)1 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)1 InternetProtocolFamily (io.netty.channel.socket.InternetProtocolFamily)1 DatagramDnsQuery (io.netty.handler.codec.dns.DatagramDnsQuery)1 DefaultDnsQuestion (io.netty.handler.codec.dns.DefaultDnsQuestion)1 DnsResponseCode (io.netty.handler.codec.dns.DnsResponseCode)1 DnsException (io.vertx.core.dns.DnsException)1 DnsResponseCode (io.vertx.core.dns.DnsResponseCode)1 LinkedHashMap (java.util.LinkedHashMap)1