📄 dnsserver.java
字号:
.append("."); getLogger().error(logBuffer.toString()); } } else { servers.addAll(cnameMXrecords); } } } } /** * Looks up DNS records of the specified type for the specified name. * * This method is a public wrapper for the private implementation * method * * @param name the name of the host to be looked up * @param type the type of record desired */ public Record[] lookup(String name, int type) { return rawDNSLookup(name,false,type); } /** * Looks up DNS records of the specified type for the specified name * * @param namestr the name of the host to be looked up * @param querysent whether the query has already been sent to the DNS servers * @param type the type of record desired */ private Record[] rawDNSLookup(String namestr, boolean querysent, int type) { Name name = null; try { name = Name.fromString(namestr, Name.root); } catch (TextParseException tpe) { // TODO: Figure out how to handle this correctly. getLogger().error("Couldn't parse name " + namestr, tpe); return null; } int dclass = DClass.IN; SetResponse cached = cache.lookupRecords(name, type, dnsCredibility); if (cached.isSuccessful()) { getLogger().debug(new StringBuffer(256) .append("Retrieving MX record for ") .append(name).append(" from cache") .toString()); return processSetResponse(cached); } else if (cached.isNXDOMAIN() || cached.isNXRRSET()) { return null; } else if (querysent) { return null; } else { getLogger().debug(new StringBuffer(256) .append("Looking up MX record for ") .append(name) .toString()); Record question = Record.newRecord(name, type, dclass); Message query = Message.newQuery(question); Message response = null; try { response = resolver.send(query); } catch (Exception ex) { getLogger().warn("Query error!", ex); return null; } int rcode = response.getHeader().getRcode(); if (rcode == Rcode.NOERROR || rcode == Rcode.NXDOMAIN) { cached = cache.addMessage(response); if (cached != null && cached.isSuccessful()) { return processSetResponse(cached); } } if (rcode != Rcode.NOERROR) { return null; } return rawDNSLookup(namestr, true, type); } } protected Record[] processSetResponse(SetResponse sr) { Record [] answers; int answerCount = 0, n = 0; RRset [] rrsets = sr.answers(); answerCount = 0; for (int i = 0; i < rrsets.length; i++) { answerCount += rrsets[i].size(); } answers = new Record[answerCount]; for (int i = 0; i < rrsets.length; i++) { Iterator iter = rrsets[i].rrs(); while (iter.hasNext()) { Record r = (Record)iter.next(); answers[n++] = r; } } return answers; } /* RFC 2821 section 5 requires that we sort the MX records by their * preference, and introduce a randomization. This Comparator does * comparisons as normal unless the values are equal, in which case * it "tosses a coin", randomly speaking. * * This way MX record w/preference 0 appears before MX record * w/preference 1, but a bunch of MX records with the same preference * would appear in different orders each time. * * Reminder for maintainers: the return value on a Comparator can * be counter-intuitive for those who aren't used to the old C * strcmp function: * * < 0 ==> a < b * = 0 ==> a = b * > 0 ==> a > b */ private static class MXRecordComparator implements Comparator { private final static Random random = new Random(); public int compare (Object a, Object b) { int pa = ((MXRecord)a).getPriority(); int pb = ((MXRecord)b).getPriority(); return (pa == pb) ? (512 - random.nextInt(1024)) : pa - pb; } } /* * Returns an Iterator over org.apache.mailet.HostAddress, a * specialized subclass of javax.mail.URLName, which provides * location information for servers that are specified as mail * handlers for the given hostname. This is done using MX records, * and the HostAddress instances are returned sorted by MX priority. * If no host is found for domainName, the Iterator returned will be * empty and the first call to hasNext() will return false. The * Iterator is a nested iterator: the outer iteration is over the * results of the MX record lookup, and the inner iteration is over * potentially multiple A records for each MX record. DNS lookups * are deferred until actually needed. * * @since v2.2.0a16-unstable * @param domainName - the domain for which to find mail servers * @return an Iterator over HostAddress instances, sorted by priority */ public Iterator getSMTPHostAddresses(final String domainName) { return new Iterator() { private Iterator mxHosts = findMXRecords(domainName).iterator(); private Iterator addresses = null; public boolean hasNext() { /* Make sure that when next() is called, that we can * provide a HostAddress. This means that we need to * have an inner iterator, and verify that it has * addresses. We could, for example, run into a * situation where the next mxHost didn't have any valid * addresses. */ if ((addresses == null || !addresses.hasNext()) && mxHosts.hasNext()) do { final String nextHostname = (String)mxHosts.next(); InetAddress[] addrs = null; try { addrs = getAllByName(nextHostname); } catch (UnknownHostException uhe) { // this should never happen, since we just got // this host from mxHosts, which should have // already done this check. StringBuffer logBuffer = new StringBuffer(128) .append("Couldn't resolve IP address for discovered host ") .append(nextHostname) .append("."); getLogger().error(logBuffer.toString()); } final InetAddress[] ipAddresses = addrs; addresses = new Iterator() { int i = 0; public boolean hasNext() { return ipAddresses != null && i < ipAddresses.length; } public Object next() { return new org.apache.mailet.HostAddress(nextHostname, "smtp://" + ipAddresses[i++].getHostAddress()); } public void remove() { throw new UnsupportedOperationException ("remove not supported by this iterator"); } }; } while (!addresses.hasNext() && mxHosts.hasNext()); return addresses != null && addresses.hasNext(); } public Object next() { return addresses != null ? addresses.next() : null; } public void remove() { throw new UnsupportedOperationException ("remove not supported by this iterator"); } }; } /* java.net.InetAddress.get[All]ByName(String) allows an IP literal * to be passed, and will recognize it even with a trailing '.'. * However, org.xbill.DNS.Address does not recognize an IP literal * with a trailing '.' character. The problem is that when we * lookup an MX record for some domains, we may find an IP address, * which will have had the trailing '.' appended by the time we get * it back from dnsjava. An MX record is not allowed to have an IP * address as the right-hand-side, but there are still plenty of * such records on the Internet. Since java.net.InetAddress can * handle them, for the time being we've decided to support them. * * These methods are NOT intended for use outside of James, and are * NOT declared by the org.apache.james.services.DNSServer. This is * currently a stopgap measure to be revisited for the next release. */ private static String allowIPLiteral(String host) { if ((host.charAt(host.length() - 1) == '.')) { String possible_ip_literal = host.substring(0, host.length() - 1); if (org.xbill.DNS.Address.isDottedQuad(possible_ip_literal)) { host = possible_ip_literal; } } return host; } /** * @see java.net.InetAddress#getByName(String) */ public static InetAddress getByName(String host) throws UnknownHostException { return org.xbill.DNS.Address.getByName(allowIPLiteral(host)); } /** * @see java.net.InetAddress#getByAllName(String) */ public static InetAddress[] getAllByName(String host) throws UnknownHostException { return org.xbill.DNS.Address.getAllByName(allowIPLiteral(host)); } /** * The dispose operation is called at the end of a components lifecycle. * Instances of this class use this method to release and destroy any * resources that they own. * * This implementation no longer shuts down org.xbill.DNS.Cache * because dnsjava 2.0.0 removed the need for a cleaner thread! * * @throws Exception if an error is encountered during shutdown */ public void dispose() { } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -