jdk/src/share/classes/com/sun/jndi/dns/Resolver.java
author ohair
Tue, 25 May 2010 15:58:33 -0700
changeset 5506 202f599c92aa
parent 2 90ce3da70b43
child 10324 e28265130e4f
permissions -rw-r--r--
6943119: Rebrand source copyright notices Reviewed-by: darcy, weijun
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     2
 * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package com.sun.jndi.dns;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import javax.naming.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * The Resolver class performs DNS client operations in support of DnsContext.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * <p> Every DnsName instance passed to or returned from a method of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * this class should be fully-qualified and contain a root label (an
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 * empty component at position 0).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * @author Scott Seligman
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
class Resolver {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    private DnsClient dnsClient;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    private int timeout;                // initial timeout on UDP queries in ms
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    private int retries;                // number of UDP retries
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
     * Constructs a new Resolver given its servers and timeout parameters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
     * Each server is of the form "server[:port]".
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
     * IPv6 literal host names include delimiting brackets.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
     * There must be at least one server.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
     * "timeout" is the initial timeout interval (in ms) for UDP queries,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
     * and "retries" gives the number of retries per server.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    Resolver(String[] servers, int timeout, int retries)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
            throws NamingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
        this.timeout = timeout;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
        this.retries = retries;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
        dnsClient = new DnsClient(servers, timeout, retries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    public void close() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
        dnsClient.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
        dnsClient = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
     * Queries resource records of a particular class and type for a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
     * given domain name.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
     * Useful values of rrclass are ResourceRecord.[Q]CLASS_xxx.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
     * Useful values of rrtype are ResourceRecord.[Q]TYPE_xxx.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
     * If recursion is true, recursion is requested on the query.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
     * If auth is true, only authoritative responses are accepted.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    ResourceRecords query(DnsName fqdn, int rrclass, int rrtype,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
                          boolean recursion, boolean auth)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
            throws NamingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
        return dnsClient.query(fqdn, rrclass, rrtype, recursion, auth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
     * Queries all resource records of a zone given its domain name and class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
     * If recursion is true, recursion is requested on the query to find
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
     * the name server (and also on the zone transfer, but it won't matter).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    ResourceRecords queryZone(DnsName zone, int rrclass, boolean recursion)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
            throws NamingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        DnsClient cl =
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
            new DnsClient(findNameServers(zone, recursion), timeout, retries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
            return cl.queryZone(zone, rrclass, recursion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
            cl.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
     * Finds the zone of a given domain name.  The method is to look
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * for the first SOA record on the path from the given domain to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     * the root.  This search may be partially bypassed if the zone's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
     * SOA record is received in the authority section of a response.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
     * If recursion is true, recursion is requested on any queries.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    DnsName findZoneName(DnsName fqdn, int rrclass, boolean recursion)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
            throws NamingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        fqdn = (DnsName) fqdn.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        while (fqdn.size() > 1) {       // while below root
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
            ResourceRecords rrs = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
                rrs = query(fqdn, rrclass, ResourceRecord.TYPE_SOA,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
                            recursion, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
            } catch (NameNotFoundException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
                throw e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
            } catch (NamingException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
                // Ignore error and keep searching up the tree.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
            if (rrs != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
                if (rrs.answer.size() > 0) {    // found zone's SOA
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
                    return fqdn;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
                // Look for an SOA record giving the zone's top node.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
                for (int i = 0; i < rrs.authority.size(); i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
                    ResourceRecord rr = (ResourceRecord)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
                        rrs.authority.elementAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
                    if (rr.getType() == ResourceRecord.TYPE_SOA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
                        DnsName zone = rr.getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
                        if (fqdn.endsWith(zone)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
                            return zone;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            fqdn.remove(fqdn.size() - 1);       // one step rootward
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        return fqdn;                    // no SOA found below root, so
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
                                        // return root
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
     * Finds a zone's SOA record.  Returns null if no SOA is found (in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
     * which case "zone" is not actually a zone).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
     * If recursion is true, recursion is requested on the query.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
     ResourceRecord findSoa(DnsName zone, int rrclass, boolean recursion)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            throws NamingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        ResourceRecords rrs = query(zone, rrclass, ResourceRecord.TYPE_SOA,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
                                    recursion, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
        for (int i = 0; i < rrs.answer.size(); i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            ResourceRecord rr = (ResourceRecord) rrs.answer.elementAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            if (rr.getType() == ResourceRecord.TYPE_SOA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                return rr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
     * Finds the name servers of a zone.  <tt>zone</tt> is a fully-qualified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
     * domain name at the top of a zone.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
     * If recursion is true, recursion is requested on the query.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    private String[] findNameServers(DnsName zone, boolean recursion)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
            throws NamingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        // %%% As an optimization, could look in authority section of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        // findZoneName() response first.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
        ResourceRecords rrs =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            query(zone, ResourceRecord.CLASS_INTERNET, ResourceRecord.TYPE_NS,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
                  recursion, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        String[] ns = new String[rrs.answer.size()];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        for (int i = 0; i < ns.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
            ResourceRecord rr = (ResourceRecord)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                rrs.answer.elementAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            if (rr.getType() != ResourceRecord.TYPE_NS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                throw new CommunicationException("Corrupted DNS message");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
            ns[i] = (String) rr.getRdata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
            // Server name will be passed to InetAddress.getByName(), which
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
            // may not be able to handle a trailing dot.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
            // assert ns[i].endsWith(".");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            ns[i] = ns[i].substring(0, ns[i].length() - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        return ns;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
}