1 4 package com.tc.net; 5 6 import com.tc.process.StreamCollector; 7 import com.tc.util.runtime.Os; 8 9 import java.io.BufferedReader ; 10 import java.io.File ; 11 import java.io.FileInputStream ; 12 import java.io.IOException ; 13 import java.io.InputStreamReader ; 14 import java.io.StringBufferInputStream ; 15 import java.io.StringReader ; 16 import java.util.Properties ; 17 import java.util.regex.Matcher ; 18 import java.util.regex.Pattern ; 19 20 22 public class EphemeralPorts { 23 24 private static Range range = null; 25 26 public synchronized static Range getRange() { 27 if (range == null) { 28 range = findRange(); 29 } 30 return range; 31 } 32 33 private static Range findRange() { 34 if (Os.isLinux()) { return new Linux().getRange(); } 35 if (Os.isSolaris()) { return new Solaris().getRange(); } 36 if (Os.isMac()) { return new Mac().getRange(); } 37 if (Os.isWindows()) { return new Windows().getRange(); } 38 39 throw new AssertionError ("No support for this OS: " + Os.getOsName()); 40 } 41 42 public static class Range { 43 private final int upper; 44 private final int lower; 45 46 private Range(int lower, int upper) { 47 this.lower = lower; 48 this.upper = upper; 49 } 50 51 public int getUpper() { 52 return upper; 53 } 54 55 public int getLower() { 56 return lower; 57 } 58 59 public String toString() { 60 return lower + " " + upper; 61 } 62 63 } 64 65 private interface RangeGetter { 66 Range getRange(); 67 } 68 69 private static class Solaris implements RangeGetter { 70 public Range getRange() { 71 Exec exec = new Exec(new String [] { "/usr/sbin/ndd", "/dev/tcp", "tcp_smallest_anon_port" }); 72 final String lower; 73 try { 74 lower = exec.execute(Exec.STDOUT); 75 } catch (Exception e) { 76 throw new RuntimeException (e); 77 } 78 79 exec = new Exec(new String [] { "/usr/sbin/ndd", "/dev/tcp", "tcp_largest_anon_port" }); 80 final String upper; 81 try { 82 upper = exec.execute(Exec.STDOUT); 83 } catch (Exception e) { 84 throw new RuntimeException (e); 85 } 86 87 int low = Integer.parseInt(lower.replaceAll("\n", "")); 88 int high = Integer.parseInt(upper.replaceAll("\n", "")); 89 90 return new Range(low, high); 91 } 92 } 93 94 private static class Windows implements RangeGetter { 95 private static final int DEFAULT_LOWER = 1024; 96 private static final int DEFAULT_UPPER = 5000; 97 98 public Range getRange() { 99 try { 100 String sysRoot = Os.findWindowsSystemRoot(); 102 if (sysRoot != null) { 103 File regExe = new File (new File (sysRoot, "system32"), "reg.exe"); 104 if (regExe.exists()) { 105 String [] cmd = new String [] { regExe.getAbsolutePath(), "query", 106 "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "/v", "MaxUserPort" }; 107 Exec exec = new Exec(cmd); 108 BufferedReader reader = new BufferedReader (new StringReader (exec.execute(Exec.STDOUT))); 109 110 Pattern pattern = Pattern.compile("^.*MaxUserPort\\s+REG_DWORD\\s+0x(\\p{XDigit}+)"); 111 String line = null; 112 while ((line = reader.readLine()) != null) { 113 Matcher matcher = pattern.matcher(line); 114 if (matcher.matches()) { 115 int val = Integer.parseInt(matcher.group(1), 16); 116 return new Range(DEFAULT_LOWER, val); 117 } 118 } 119 } 120 } 121 } catch (Exception e) { 122 e.printStackTrace(); 123 } 124 125 return new Range(DEFAULT_LOWER, DEFAULT_UPPER); 126 } 127 } 128 129 private static class Mac implements RangeGetter { 130 public Range getRange() { 131 Exec exec = new Exec(new String [] { "sysctl", "net.inet.ip.portrange" }); 132 final String output; 133 try { 134 output = exec.execute(Exec.STDOUT); 135 } catch (Exception e) { 136 throw new RuntimeException (e); 137 } 138 139 Properties props = new Properties (); 140 try { 141 props.load(new StringBufferInputStream (output)); 142 } catch (IOException e) { 143 throw new RuntimeException (e); 144 } 145 146 int low = Integer.parseInt(props.getProperty("net.inet.ip.portrange.hifirst")); 147 int high = Integer.parseInt(props.getProperty("net.inet.ip.portrange.hilast")); 148 149 return new Range(low, high); 150 } 151 } 152 153 private static class Linux implements RangeGetter { 154 private static final String source = "/proc/sys/net/ipv4/ip_local_port_range"; 155 156 public Range getRange() { 157 File src = new File (source); 158 if (!src.exists() || !src.canRead()) { throw new RuntimeException ("Cannot access " + source); } 159 160 BufferedReader reader = null; 161 try { 162 reader = new BufferedReader (new InputStreamReader (new FileInputStream (src))); 163 String data = reader.readLine(); 164 String [] parts = data.split("[ \\t]"); 165 if (parts.length != 2) { throw new RuntimeException ("Wrong number of tokens (" + parts.length + ") in " + data); } 166 167 int low = Integer.parseInt(parts[0]); 168 int high = Integer.parseInt(parts[1]); 169 170 return new Range(low, high); 171 } catch (IOException ioe) { 172 throw new RuntimeException (ioe); 173 } finally { 174 if (reader != null) { 175 try { 176 reader.close(); 177 } catch (IOException e) { 178 } 180 } 181 } 182 } 183 } 184 185 private static class Exec { 186 static final int STDOUT = 1; 187 static final int STDERR = 2; 188 189 private final String [] cmd; 190 191 Exec(String cmd[]) { 192 this.cmd = cmd; 193 } 194 195 String execute(int stream) throws IOException , InterruptedException { 196 if ((stream != STDOUT) && (stream != STDERR)) { throw new IllegalArgumentException ("bad stream: " + stream); } 197 198 Process proc = Runtime.getRuntime().exec(cmd); 199 proc.getOutputStream().close(); 200 201 StreamCollector out = new StreamCollector(proc.getInputStream()); 202 StreamCollector err = new StreamCollector(proc.getErrorStream()); 203 out.start(); 204 err.start(); 205 206 proc.waitFor(); 208 out.join(); 209 err.join(); 210 211 if (stream == STDOUT) { return out.toString(); } 212 return err.toString(); 213 } 214 215 } 216 217 } 218 | Popular Tags |