/*
 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.dns;


import javax.naming.*;


The Resolver class performs DNS client operations in support of DnsContext.

Every DnsName instance passed to or returned from a method of this class should be fully-qualified and contain a root label (an empty component at position 0).

Author:Scott Seligman
/** * The Resolver class performs DNS client operations in support of DnsContext. * * <p> Every DnsName instance passed to or returned from a method of * this class should be fully-qualified and contain a root label (an * empty component at position 0). * * @author Scott Seligman */
class Resolver { private DnsClient dnsClient; private int timeout; // initial timeout on UDP queries in ms private int retries; // number of UDP retries /* * Constructs a new Resolver given its servers and timeout parameters. * Each server is of the form "server[:port]". * IPv6 literal host names include delimiting brackets. * There must be at least one server. * "timeout" is the initial timeout interval (in ms) for UDP queries, * and "retries" gives the number of retries per server. */ Resolver(String[] servers, int timeout, int retries) throws NamingException { this.timeout = timeout; this.retries = retries; dnsClient = new DnsClient(servers, timeout, retries); } public void close() { dnsClient.close(); dnsClient = null; } /* * Queries resource records of a particular class and type for a * given domain name. * Useful values of rrclass are ResourceRecord.[Q]CLASS_xxx. * Useful values of rrtype are ResourceRecord.[Q]TYPE_xxx. * If recursion is true, recursion is requested on the query. * If auth is true, only authoritative responses are accepted. */ ResourceRecords query(DnsName fqdn, int rrclass, int rrtype, boolean recursion, boolean auth) throws NamingException { return dnsClient.query(fqdn, rrclass, rrtype, recursion, auth); } /* * Queries all resource records of a zone given its domain name and class. * If recursion is true, recursion is requested on the query to find * the name server (and also on the zone transfer, but it won't matter). */ ResourceRecords queryZone(DnsName zone, int rrclass, boolean recursion) throws NamingException { DnsClient cl = new DnsClient(findNameServers(zone, recursion), timeout, retries); try { return cl.queryZone(zone, rrclass, recursion); } finally { cl.close(); } } /* * Finds the zone of a given domain name. The method is to look * for the first SOA record on the path from the given domain to * the root. This search may be partially bypassed if the zone's * SOA record is received in the authority section of a response. * If recursion is true, recursion is requested on any queries. */ DnsName findZoneName(DnsName fqdn, int rrclass, boolean recursion) throws NamingException { fqdn = (DnsName) fqdn.clone(); while (fqdn.size() > 1) { // while below root ResourceRecords rrs = null; try { rrs = query(fqdn, rrclass, ResourceRecord.TYPE_SOA, recursion, false); } catch (NameNotFoundException e) { throw e; } catch (NamingException e) { // Ignore error and keep searching up the tree. } if (rrs != null) { if (rrs.answer.size() > 0) { // found zone's SOA return fqdn; } // Look for an SOA record giving the zone's top node. for (int i = 0; i < rrs.authority.size(); i++) { ResourceRecord rr = rrs.authority.elementAt(i); if (rr.getType() == ResourceRecord.TYPE_SOA) { DnsName zone = rr.getName(); if (fqdn.endsWith(zone)) { return zone; } } } } fqdn.remove(fqdn.size() - 1); // one step rootward } return fqdn; // no SOA found below root, so // return root } /* * Finds a zone's SOA record. Returns null if no SOA is found (in * which case "zone" is not actually a zone). * If recursion is true, recursion is requested on the query. */ ResourceRecord findSoa(DnsName zone, int rrclass, boolean recursion) throws NamingException { ResourceRecords rrs = query(zone, rrclass, ResourceRecord.TYPE_SOA, recursion, false); for (int i = 0; i < rrs.answer.size(); i++) { ResourceRecord rr = rrs.answer.elementAt(i); if (rr.getType() == ResourceRecord.TYPE_SOA) { return rr; } } return null; } /* * Finds the name servers of a zone. <tt>zone</tt> is a fully-qualified * domain name at the top of a zone. * If recursion is true, recursion is requested on the query. */ private String[] findNameServers(DnsName zone, boolean recursion) throws NamingException { // %%% As an optimization, could look in authority section of // findZoneName() response first. ResourceRecords rrs = query(zone, ResourceRecord.CLASS_INTERNET, ResourceRecord.TYPE_NS, recursion, false); String[] ns = new String[rrs.answer.size()]; for (int i = 0; i < ns.length; i++) { ResourceRecord rr = rrs.answer.elementAt(i); if (rr.getType() != ResourceRecord.TYPE_NS) { throw new CommunicationException("Corrupted DNS message"); } ns[i] = (String) rr.getRdata(); // Server name will be passed to InetAddress.getByName(), which // may not be able to handle a trailing dot. // assert ns[i].endsWith("."); ns[i] = ns[i].substring(0, ns[i].length() - 1); } return ns; } }