1/* 2 * Copyright (c) 1998, 2014, 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 26package sun.net; 27 28import java.security.PrivilegedAction; 29import java.security.Security; 30 31public final class InetAddressCachePolicy { 32 33 // Controls the cache policy for successful lookups only 34 private static final String cachePolicyProp = "networkaddress.cache.ttl"; 35 private static final String cachePolicyPropFallback = 36 "sun.net.inetaddr.ttl"; 37 38 // Controls the cache policy for negative lookups only 39 private static final String negativeCachePolicyProp = 40 "networkaddress.cache.negative.ttl"; 41 private static final String negativeCachePolicyPropFallback = 42 "sun.net.inetaddr.negative.ttl"; 43 44 public static final int FOREVER = -1; 45 public static final int NEVER = 0; 46 47 /* default value for positive lookups */ 48 public static final int DEFAULT_POSITIVE = 30; 49 50 /* The Java-level namelookup cache policy for successful lookups: 51 * 52 * -1: caching forever 53 * any positive value: the number of seconds to cache an address for 54 * 55 * default value is forever (FOREVER), as we let the platform do the 56 * caching. For security reasons, this caching is made forever when 57 * a security manager is set. 58 */ 59 private static volatile int cachePolicy = FOREVER; 60 61 /* The Java-level namelookup cache policy for negative lookups: 62 * 63 * -1: caching forever 64 * any positive value: the number of seconds to cache an address for 65 * 66 * default value is 0. It can be set to some other value for 67 * performance reasons. 68 */ 69 private static volatile int negativeCachePolicy = NEVER; 70 71 /* 72 * Whether or not the cache policy for successful lookups was set 73 * using a property (cmd line). 74 */ 75 private static boolean propertySet; 76 77 /* 78 * Whether or not the cache policy for negative lookups was set 79 * using a property (cmd line). 80 */ 81 private static boolean propertyNegativeSet; 82 83 /* 84 * Initialize 85 */ 86 static { 87 88 Integer tmp = java.security.AccessController.doPrivileged( 89 new PrivilegedAction<Integer>() { 90 public Integer run() { 91 try { 92 String tmpString = Security.getProperty(cachePolicyProp); 93 if (tmpString != null) { 94 return Integer.valueOf(tmpString); 95 } 96 } catch (NumberFormatException ignored) { 97 // Ignore 98 } 99 100 try { 101 String tmpString = System.getProperty(cachePolicyPropFallback); 102 if (tmpString != null) { 103 return Integer.decode(tmpString); 104 } 105 } catch (NumberFormatException ignored) { 106 // Ignore 107 } 108 return null; 109 } 110 }); 111 112 if (tmp != null) { 113 cachePolicy = tmp < 0 ? FOREVER : tmp; 114 propertySet = true; 115 } else { 116 /* No properties defined for positive caching. If there is no 117 * security manager then use the default positive cache value. 118 */ 119 if (System.getSecurityManager() == null) { 120 cachePolicy = DEFAULT_POSITIVE; 121 } 122 } 123 tmp = java.security.AccessController.doPrivileged ( 124 new PrivilegedAction<Integer>() { 125 public Integer run() { 126 try { 127 String tmpString = Security.getProperty(negativeCachePolicyProp); 128 if (tmpString != null) { 129 return Integer.valueOf(tmpString); 130 } 131 } catch (NumberFormatException ignored) { 132 // Ignore 133 } 134 135 try { 136 String tmpString = System.getProperty(negativeCachePolicyPropFallback); 137 if (tmpString != null) { 138 return Integer.decode(tmpString); 139 } 140 } catch (NumberFormatException ignored) { 141 // Ignore 142 } 143 return null; 144 } 145 }); 146 147 if (tmp != null) { 148 negativeCachePolicy = tmp < 0 ? FOREVER : tmp; 149 propertyNegativeSet = true; 150 } 151 } 152 153 public static int get() { 154 return cachePolicy; 155 } 156 157 public static int getNegative() { 158 return negativeCachePolicy; 159 } 160 161 /** 162 * Sets the cache policy for successful lookups if the user has not 163 * already specified a cache policy for it using a 164 * command-property. 165 * @param newPolicy the value in seconds for how long the lookup 166 * should be cached 167 */ 168 public static synchronized void setIfNotSet(int newPolicy) { 169 /* 170 * When setting the new value we may want to signal that the 171 * cache should be flushed, though this doesn't seem strictly 172 * necessary. 173 */ 174 if (!propertySet) { 175 checkValue(newPolicy, cachePolicy); 176 cachePolicy = newPolicy; 177 } 178 } 179 180 /** 181 * Sets the cache policy for negative lookups if the user has not 182 * already specified a cache policy for it using a 183 * command-property. 184 * @param newPolicy the value in seconds for how long the lookup 185 * should be cached 186 */ 187 public static void setNegativeIfNotSet(int newPolicy) { 188 /* 189 * When setting the new value we may want to signal that the 190 * cache should be flushed, though this doesn't seem strictly 191 * necessary. 192 */ 193 if (!propertyNegativeSet) { 194 // Negative caching does not seem to have any security 195 // implications. 196 // checkValue(newPolicy, negativeCachePolicy); 197 // but we should normalize negative policy 198 negativeCachePolicy = newPolicy < 0 ? FOREVER : newPolicy; 199 } 200 } 201 202 private static void checkValue(int newPolicy, int oldPolicy) { 203 /* 204 * If malicious code gets a hold of this method, prevent 205 * setting the cache policy to something laxer or some 206 * invalid negative value. 207 */ 208 if (newPolicy == FOREVER) 209 return; 210 211 if ((oldPolicy == FOREVER) || 212 (newPolicy < oldPolicy) || 213 (newPolicy < FOREVER)) { 214 215 throw new 216 SecurityException("can't make InetAddress cache more lax"); 217 } 218 } 219} 220