/*
 * Copyright 2000-2005 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.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();
    }
}
