1 /* 2 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.net.dns; 27 28 import java.util.List; 29 import java.util.LinkedList; 30 import java.util.StringTokenizer; 31 import java.io.BufferedReader; 32 import java.io.FileReader; 33 import java.io.IOException; 34 35 /* 36 * An implementation of ResolverConfiguration for Solaris 37 * and Linux. 38 */ 39 40 public class ResolverConfigurationImpl 41 extends ResolverConfiguration 42 { 43 // Lock helds whilst loading configuration or checking 44 private static Object lock = new Object(); 45 46 // Time of last refresh. 47 private static long lastRefresh = -1; 48 49 // Cache timeout (300 seconds) - should be converted into property 50 // or configured as preference in the future. 51 private static final int TIMEOUT = 300000; 52 53 // Resolver options 54 private final Options opts; 55 56 // Parse /etc/resolv.conf to get the values for a particular 57 // keyword. 58 // 59 private LinkedList<String> resolvconf(String keyword, 60 int maxperkeyword, 61 int maxkeywords) 62 { 63 LinkedList<String> ll = new LinkedList<String>(); 64 65 try { 66 BufferedReader in = 67 new BufferedReader(new FileReader("/etc/resolv.conf")); 68 String line; 69 while ((line = in.readLine()) != null) { 70 int maxvalues = maxperkeyword; 71 if (line.length() == 0) 72 continue; 73 if (line.charAt(0) == '#' || line.charAt(0) == ';') 74 continue; 75 if (!line.startsWith(keyword)) 76 continue; 77 String value = line.substring(keyword.length()); 78 if (value.length() == 0) 79 continue; 80 if (value.charAt(0) != ' ' && value.charAt(0) != '\t') 81 continue; 82 StringTokenizer st = new StringTokenizer(value, " \t"); 83 while (st.hasMoreTokens()) { 84 String val = st.nextToken(); 85 if (val.charAt(0) == '#' || val.charAt(0) == ';') { 86 break; 87 } 88 ll.add(val); 89 if (--maxvalues == 0) { 90 break; 91 } 92 } 93 if (--maxkeywords == 0) { 94 break; 95 } 96 } 97 in.close(); 98 } catch (IOException ioe) { 99 // problem reading value 100 } 101 102 return ll; 103 } 104 105 private LinkedList<String> searchlist; 106 private LinkedList<String> nameservers; 107 108 109 // Load DNS configuration from OS 110 111 private void loadConfig() { 112 assert Thread.holdsLock(lock); 113 114 // check if cached settings have expired. 115 if (lastRefresh >= 0) { 116 long currTime = System.currentTimeMillis(); 117 if ((currTime - lastRefresh) < TIMEOUT) { 118 return; 119 } 120 } 121 122 // get the name servers from /etc/resolv.conf 123 nameservers = 124 java.security.AccessController.doPrivileged( 125 new java.security.PrivilegedAction<LinkedList<String>>() { 126 public LinkedList<String> run() { 127 // typically MAXNS is 3 but we've picked 5 here 128 // to allow for additional servers if required. 129 return resolvconf("nameserver", 1, 5); 130 } /* run */ 131 }); 132 133 // get the search list (or domain) 134 searchlist = getSearchList(); 135 136 // update the timestamp on the configuration 137 lastRefresh = System.currentTimeMillis(); 138 } 139 140 141 // obtain search list or local domain 142 143 private LinkedList<String> getSearchList() { 144 145 LinkedList<String> sl; 146 147 // first try the search keyword in /etc/resolv.conf 148 149 sl = java.security.AccessController.doPrivileged( 150 new java.security.PrivilegedAction<LinkedList<String>>() { 151 public LinkedList<String> run() { 152 LinkedList<String> ll; 153 154 // first try search keyword (max 6 domains) 155 ll = resolvconf("search", 6, 1); 156 if (ll.size() > 0) { 157 return ll; 158 } 159 160 return null; 161 162 } /* run */ 163 164 }); 165 if (sl != null) { 166 return sl; 167 } 168 169 // No search keyword so use local domain 170 171 172 // LOCALDOMAIN has absolute priority on Solaris 173 174 String localDomain = localDomain0(); 175 if (localDomain != null && localDomain.length() > 0) { 176 sl = new LinkedList<String>(); 177 sl.add(localDomain); 178 return sl; 179 } 180 181 // try domain keyword in /etc/resolv.conf 182 183 sl = java.security.AccessController.doPrivileged( 184 new java.security.PrivilegedAction<LinkedList<String>>() { 185 public LinkedList<String> run() { 186 LinkedList<String> ll; 187 188 ll = resolvconf("domain", 1, 1); 189 if (ll.size() > 0) { 190 return ll; 191 } 192 return null; 193 194 } /* run */ 195 }); 196 if (sl != null) { 197 return sl; 198 } 199 200 // no local domain so try fallback (RPC) domain or 201 // hostName 202 203 sl = new LinkedList<String>(); 204 String domain = fallbackDomain0(); 205 if (domain != null && domain.length() > 0) { 206 sl.add(domain); 207 } 208 209 return sl; 210 } 211 212 213 // ---- 214 215 ResolverConfigurationImpl() { 216 opts = new OptionsImpl(); 217 } 218 219 @SuppressWarnings("unchecked") 220 public List<String> searchlist() { 221 synchronized (lock) { 222 loadConfig(); 223 224 // List is mutable so return a shallow copy 225 return (List<String>)searchlist.clone(); 226 } 227 } 228 229 @SuppressWarnings("unchecked") 230 public List<String> nameservers() { 231 synchronized (lock) { 232 loadConfig(); 233 234 // List is mutable so return a shallow copy 235 236 return (List<String>)nameservers.clone(); 237 238 } 239 } 240 241 public Options options() { 242 return opts; 243 } 244 245 246 // --- Native methods -- 247 248 static native String localDomain0(); 249 250 static native String fallbackDomain0(); 251 252 static { 253 java.security.AccessController.doPrivileged( 254 new sun.security.action.LoadLibraryAction("net")); 255 } 256 257 } 258 259 /** 260 * Implementation of {@link ResolverConfiguration.Options} 261 */ 262 class OptionsImpl extends ResolverConfiguration.Options { 263 }