/*
 * Copyright (c) 2000, 2005, 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 sun.net.spi.nameservice.dns;

import java.lang.ref.SoftReference;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.spi.NamingManager;
import java.util.*;
import sun.net.util.IPAddressUtil;
import sun.net.dns.ResolverConfiguration;
import sun.net.spi.nameservice.*;
import java.security.AccessController;
import sun.security.action.*;

/*
 * A name service provider based on JNDI-DNS.
 */

public final class DNSNameService implements NameService {

    // List of domains specified by property
    private LinkedList domainList = null;

    // JNDI-DNS URL for name servers specified via property
    private String nameProviderUrl = null;

    // Per-thread soft cache of the last temporary context
    private static ThreadLocal contextRef = new ThreadLocal();

    // Simple class to encapsulate the temporary context
    private static class ThreadContext {
        private DirContext dirCtxt;
        private List nsList;

        public ThreadContext(DirContext dirCtxt, List nsList) {
            this.dirCtxt = dirCtxt;
            this.nsList = nsList;
        }

        public DirContext dirContext() {
            return dirCtxt;
        }

        public List nameservers() {
            return nsList;
        }
    }

    // Returns a per-thread DirContext
    private DirContext getTemporaryContext() throws NamingException {
        SoftReference ref = (SoftReference)contextRef.get();
        ThreadContext thrCtxt = null;
        List nsList = null;

        // if no property specified we need to obtain the list of servers
        //
        if (nameProviderUrl == null)
            nsList = ResolverConfiguration.open().nameservers();

        // if soft reference hasn't been gc'ed no property has been
        // specified then we need to check if the DNS configuration
        // has changed.
        //
        if ((ref != null) && ((thrCtxt = (ThreadContext)ref.get()) != null)) {
            if (nameProviderUrl == null) {
                if (!thrCtxt.nameservers().equals(nsList)) {
                    // DNS configuration has changed
                    thrCtxt = null;
                }
            }
        }

        // new thread context needs to be created
        if (thrCtxt == null) {
            final Hashtable<String,Object> env = new Hashtable<String,Object>();
            env.put("java.naming.factory.initial",
                    "com.sun.jndi.dns.DnsContextFactory");

            // If no nameservers property specified we create provider URL
            // based on system configured name servers
            //
            String provUrl = nameProviderUrl;
            if (provUrl == null) {
                provUrl = createProviderURL(nsList);
                if (provUrl.length() == 0) {
                    throw new RuntimeException("bad nameserver configuration");
                }
            }
            env.put("java.naming.provider.url", provUrl);

            // Need to create directory context in privileged block
            // as JNDI-DNS needs to resolve the name servers.
            //
            DirContext dirCtxt;
            try {
                dirCtxt = (DirContext)
                    java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedExceptionAction() {
                            public Object run() throws NamingException {
                                // Create the DNS context using NamingManager rather than using
                                // the initial context constructor. This avoids having the initial
                                // context constructor call itself.
                                Context ctx = NamingManager.getInitialContext(env);
                                if (!(ctx instanceof DirContext)) {
                                    return null; // cannot create a DNS context
                                }
                                return ctx;
                            }
                    });
            } catch (java.security.PrivilegedActionException pae) {
                throw (NamingException)pae.getException();
            }

            // create new soft reference to our thread context
            //
            thrCtxt = new ThreadContext(dirCtxt, nsList);
            contextRef.set(new SoftReference(thrCtxt));
        }

        return thrCtxt.dirContext();
    }

    /**
     * Resolves the specified entry in DNS.
     *
     * Canonical name records are recursively resolved (to a maximum
     * of 5 to avoid performance hit and potential CNAME loops).
     *
     * @param   ctx     JNDI directory context
     * @param   name    name to resolve
     * @param   ids     record types to search
     * @param   depth   call depth - pass as 0.
     *
     * @return  array list with results (will have at least on entry)
     *
     * @throws  UnknownHostException if lookup fails or other error.
     */
    private ArrayList resolve(final DirContext ctx, final String name, final String[] ids,
                              int depth) throws UnknownHostException
    {
        ArrayList results = new ArrayList();
        Attributes attrs;

        // do the query
        try {
            attrs = (Attributes)
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedExceptionAction() {
                        public Object run() throws NamingException {
                            return ctx.getAttributes(name, ids);
                        }
                });
        } catch (java.security.PrivilegedActionException pae) {
            throw new UnknownHostException(pae.getException().getMessage());
        }

        // non-requested type returned so enumeration is empty
        NamingEnumeration ne = attrs.getAll();
        if (!ne.hasMoreElements()) {
            throw new UnknownHostException("DNS record not found");
        }

        // iterate through the returned attributes
        UnknownHostException uhe = null;
        try {
            while (ne.hasMoreElements()) {
                Attribute attr = (Attribute)ne.next();
                String attrID = attr.getID();

                for (NamingEnumeration e = attr.getAll(); e.hasMoreElements();) {
                    String addr = (String)e.next();

                    // for canoncical name records do recursive lookup
                    // - also check for CNAME loops to avoid stack overflow

                    if (attrID.equals("CNAME")) {
                        if (depth > 4) {
                            throw new UnknownHostException(name + ": possible CNAME loop");
                        }
                        try {
                            results.addAll(resolve(ctx, addr, ids, depth+1));
                        } catch (UnknownHostException x) {
                            // canonical name can't be resolved.
                            if (uhe == null)
                                uhe = x;
                        }
                    } else {
                        results.add(addr);
                    }
                }
            }
        } catch (NamingException nx) {
            throw new UnknownHostException(nx.getMessage());
        }

        // pending exception as canonical name could not be resolved.
        if (results.isEmpty() && uhe != null) {
            throw uhe;
        }

        return results;
    }

    public DNSNameService() throws Exception {

        // default domain
        String domain = AccessController.doPrivileged(
            new GetPropertyAction("sun.net.spi.nameservice.domain"));
        if (domain != null && domain.length() > 0) {
            domainList = new LinkedList();
            domainList.add(domain);
        }

        // name servers
        String nameservers = AccessController.doPrivileged(
            new GetPropertyAction("sun.net.spi.nameservice.nameservers"));
        if (nameservers != null && nameservers.length() > 0) {
            nameProviderUrl = createProviderURL(nameservers);
            if (nameProviderUrl.length() == 0) {
                throw new RuntimeException("malformed nameservers property");
            }

        } else {

            // no property specified so check host DNS resolver configured
            // with at least one nameserver in dotted notation.
            //
            List nsList = ResolverConfiguration.open().nameservers();
            if (nsList.size() == 0)
                throw new RuntimeException("no nameservers provided");
            boolean found = false;
            Iterator i = nsList.iterator();
            while (i.hasNext()) {
                String addr = (String)i.next();
                if (IPAddressUtil.isIPv4LiteralAddress(addr) ||
                    IPAddressUtil.isIPv6LiteralAddress(addr)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                throw new RuntimeException("bad nameserver configuration");
            }
        }
    }

    public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {

        // DNS records that we search for
        String[] ids = {"A", "AAAA", "CNAME"};

        // first get directory context
        DirContext ctx;
        try {
            ctx = getTemporaryContext();
        } catch (NamingException nx) {
            throw new Error(nx);
        }

        ArrayList results = null;
        UnknownHostException uhe = null;

        // If host already contains a domain name then just look it up
        if (host.indexOf('.') >= 0) {
            try {
                results = resolve(ctx, host, ids, 0);
            } catch (UnknownHostException x) {
                uhe = x;
            }
        }

        // Here we try to resolve the host using the domain suffix or
        // the domain suffix search list. If the host cannot be resolved
        // using the domain suffix then we attempt devolution of
        // the suffix - eg: if we are searching for "foo" and our
        // domain suffix is "eng.sun.com" we will try to resolve
        // "foo.eng.sun.com" and "foo.sun.com".
        // It's not normal to attempt devolation with domains on the
        // domain suffix search list - however as ResolverConfiguration
        // doesn't distinguish domain or search list in the list it
        // returns we approximate by doing devolution on the domain
        // suffix if the list has one entry.

        if (results == null) {
            List searchList = null;
            Iterator i;
            boolean usingSearchList = false;

            if (domainList != null) {
                i = domainList.iterator();
            } else {
                searchList = ResolverConfiguration.open().searchlist();
                if (searchList.size() > 1) {
                    usingSearchList = true;
                }
                i = searchList.iterator();
            }

            // iterator through each domain suffix
            while (i.hasNext()) {
                String parentDomain = (String)i.next();
                int start = 0;
                while ((start = parentDomain.indexOf(".")) != -1
                       && start < parentDomain.length() -1) {
                    try {
                        results = resolve(ctx, host+"."+parentDomain, ids, 0);
                        break;
                    } catch (UnknownHostException x) {
                        uhe = x;
                        if (usingSearchList) {
                            break;
                        }

                        // devolve
                        parentDomain = parentDomain.substring(start+1);
                    }
                }
                if (results != null) {
                    break;
                }
            }
        }

        // finally try the host if it doesn't have a domain name
        if (results == null && (host.indexOf('.') < 0)) {
            results = resolve(ctx, host, ids, 0);
        }

        // if not found then throw the (last) exception thrown.
        if (results == null) {
            assert uhe != null;
            throw uhe;
        }

        /**
         * Convert the array list into a byte aray list - this
         * filters out any invalid IPv4/IPv6 addresses.
         */
        assert results.size() > 0;
        InetAddress[] addrs = new InetAddress[results.size()];
        int count = 0;
        for (int i=0; i<results.size(); i++) {
            String addrString = (String)results.get(i);
            byte addr[] = IPAddressUtil.textToNumericFormatV4(addrString);
            if (addr == null) {
                addr = IPAddressUtil.textToNumericFormatV6(addrString);
            }
            if (addr != null) {
                addrs[count++] = InetAddress.getByAddress(host, addr);
            }
        }

        /**
         * If addresses are filtered then we need to resize the
         * array. Additionally if all addresses are filtered then
         * we throw an exception.
         */
        if (count == 0) {
            throw new UnknownHostException(host + ": no valid DNS records");
        }
        if (count < results.size()) {
            InetAddress[] tmp = new InetAddress[count];
            for (int i=0; i<count; i++) {
                tmp[i] = addrs[i];
            }
            addrs = tmp;
        }

        return addrs;
    }

    /**
     * Reverse lookup code. I.E: find a host name from an IP address.
     * IPv4 addresses are mapped in the IN-ADDR.ARPA. top domain, while
     * IPv6 addresses can be in IP6.ARPA or IP6.INT.
     * In both cases the address has to be converted into a dotted form.
     */
    public String getHostByAddr(byte[] addr) throws UnknownHostException {
        String host = null;
        try {
            String literalip = "";
            String[] ids = { "PTR" };
            DirContext ctx;
            ArrayList results = null;
            try {
                ctx = getTemporaryContext();
            } catch (NamingException nx) {
                throw new Error(nx);
            }
            if (addr.length == 4) { // IPv4 Address
                for (int i = addr.length-1; i >= 0; i--) {
                    literalip += (addr[i] & 0xff) +".";
                }
                literalip += "IN-ADDR.ARPA.";

                results = resolve(ctx, literalip, ids, 0);
                host = (String)results.get(0);
            } else if (addr.length == 16) { // IPv6 Address
                /**
                 * Because RFC 3152 changed the root domain name for reverse
                 * lookups from IP6.INT. to IP6.ARPA., we need to check
                 * both. I.E. first the new one, IP6.ARPA, then if it fails
                 * the older one, IP6.INT
                 */

                for (int i = addr.length-1; i >= 0; i--) {
                    literalip += Integer.toHexString((addr[i] & 0x0f)) +"."
                        +Integer.toHexString((addr[i] & 0xf0) >> 4) +".";
                }
                String ip6lit = literalip + "IP6.ARPA.";

                try {
                    results = resolve(ctx, ip6lit, ids, 0);
                    host = (String)results.get(0);
                } catch (UnknownHostException e) {
                    host = null;
                }
                if (host == null) {
                    // IP6.ARPA lookup failed, let's try the older IP6.INT
                    ip6lit = literalip + "IP6.INT.";
                    results = resolve(ctx, ip6lit, ids, 0);
                    host = (String)results.get(0);
                }
            }
        } catch (Exception e) {
            throw new UnknownHostException(e.getMessage());
        }
        // Either we couldn't find it or the address was neither IPv4 or IPv6
        if (host == null)
            throw new UnknownHostException();
        // remove trailing dot
        if (host.endsWith(".")) {
            host = host.substring(0, host.length() - 1);
        }
        return host;
    }


    // ---------

    private static void appendIfLiteralAddress(String addr, StringBuffer sb) {
        if (IPAddressUtil.isIPv4LiteralAddress(addr)) {
            sb.append("dns://" + addr + " ");
        } else {
            if (IPAddressUtil.isIPv6LiteralAddress(addr)) {
                sb.append("dns://[" + addr + "] ");
            }
        }
    }

    /*
     * @return String containing the JNDI-DNS provider URL
     *         corresponding to the supplied List of nameservers.
     */
    private static String createProviderURL(List nsList) {
        Iterator i = nsList.iterator();
        StringBuffer sb = new StringBuffer();
        while (i.hasNext()) {
            appendIfLiteralAddress((String)i.next(), sb);
        }
        return sb.toString();
    }

    /*
     * @return String containing the JNDI-DNS provider URL
     *         corresponding to the list of nameservers
     *         contained in the provided str.
     */
    private static String createProviderURL(String str) {
        StringBuffer sb = new StringBuffer();
        StringTokenizer st = new StringTokenizer(str, ",");
        while (st.hasMoreTokens()) {
            appendIfLiteralAddress(st.nextToken(), sb);
        }
        return sb.toString();
    }
}
