001/* 002 * Copyright 2015-2018 the original author or authors 003 * 004 * This software is licensed under the Apache License, Version 2.0, 005 * the GNU Lesser General Public License version 2 or later ("LGPL") 006 * and the WTFPL. 007 * You may choose either license to govern your use of this software only 008 * upon the condition that you accept all of the terms of either 009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL. 010 */ 011package org.minidns.dnsserverlookup; 012 013import org.minidns.util.PlatformDetection; 014 015import java.io.BufferedReader; 016import java.io.File; 017import java.io.FileInputStream; 018import java.io.IOException; 019import java.io.InputStreamReader; 020import java.util.ArrayList; 021import java.util.List; 022import java.util.logging.Level; 023import java.util.logging.Logger; 024import java.util.regex.Matcher; 025import java.util.regex.Pattern; 026 027public class UnixUsingEtcResolvConf extends AbstractDnsServerLookupMechanism { 028 029 public static final DnsServerLookupMechanism INSTANCE = new UnixUsingEtcResolvConf(); 030 public static final int PRIORITY = 2000; 031 032 private static final Logger LOGGER = Logger.getLogger(UnixUsingEtcResolvConf.class.getName()); 033 034 private static final String RESOLV_CONF_FILE = "/etc/resolv.conf"; 035 private static final Pattern NAMESERVER_PATTERN = Pattern.compile("^nameserver\\s+(.*)$"); 036 037 private static List<String> cached; 038 private static long lastModified; 039 040 private UnixUsingEtcResolvConf() { 041 super(UnixUsingEtcResolvConf.class.getSimpleName(), PRIORITY); 042 } 043 044 @Override 045 public List<String> getDnsServerAddresses() { 046 File file = new File(RESOLV_CONF_FILE); 047 if (!file.exists()) { 048 // Not very unixoid systems 049 return null; 050 } 051 052 long currentLastModified = file.lastModified(); 053 if (currentLastModified == lastModified && cached != null) { 054 return cached; 055 } 056 057 List<String> servers = new ArrayList<>(); 058 BufferedReader reader = null; 059 try { 060 reader = new BufferedReader(new InputStreamReader(new FileInputStream(file))); 061 String line; 062 while ((line = reader.readLine()) != null) { 063 Matcher matcher = NAMESERVER_PATTERN.matcher(line); 064 if (matcher.matches()) { 065 servers.add(matcher.group(1).trim()); 066 } 067 } 068 } catch (IOException e) { 069 LOGGER.log(Level.WARNING, "Could not read from " + RESOLV_CONF_FILE, e); 070 return null; 071 } finally { 072 if (reader != null) try { 073 reader.close(); 074 } catch (IOException e) { 075 LOGGER.log(Level.WARNING, "Could not close reader", e); 076 } 077 } 078 079 if (servers.isEmpty()) { 080 LOGGER.fine("Could not find any nameservers in " + RESOLV_CONF_FILE); 081 return null; 082 } 083 084 cached = servers; 085 lastModified = currentLastModified; 086 087 return cached; 088 } 089 090 @Override 091 public boolean isAvailable() { 092 if (PlatformDetection.isAndroid()) { 093 // Don't rely on resolv.conf when on Android 094 return false; 095 } 096 097 File file = new File(RESOLV_CONF_FILE); 098 if (!file.exists()) { 099 // Not very unixoid systems 100 return false; 101 } 102 return true; 103 } 104 105}