comparison src/net/sourceforge/jsocks/InetRange.java @ 349:205ee2873330

update jsocks to 2011-03-19
author Carl Byington <carl@five-ten-sg.com>
date Fri, 01 Aug 2014 11:23:10 -0700
parents
children
comparison
equal deleted inserted replaced
348:29076621bab0 349:205ee2873330
1 package net.sourceforge.jsocks;
2 import java.net.InetAddress;
3 import java.net.UnknownHostException;
4 import java.util.*;
5
6 /**
7 * Class InetRange provides the means of defining the range of inetaddresses.
8 * It's used by Proxy class to store and look up addresses of machines, that
9 * should be contacted directly rather then through the proxy.
10 * <P>
11 * InetRange provides several methods to add either standalone addresses, or
12 * ranges (e.g. 100.200.300.0:100.200.300.255, which covers all addresses
13 * on on someones local network). It also provides methods for checking wether
14 * given address is in this range. Any number of ranges and standalone
15 * addresses can be added to the range.
16 */
17 public class InetRange implements Cloneable{
18
19 Hashtable host_names;
20 Vector all;
21 Vector end_names;
22
23 boolean useSeparateThread = true;
24
25 /**
26 * Creates the empty range.
27 */
28 public InetRange(){
29 all = new Vector();
30 host_names = new Hashtable();
31 end_names = new Vector();
32 }
33
34 /**
35 * Adds another host or range to this range.
36 The String can be one of those:
37 <UL>
38 <li> Host name. eg.(Athena.myhost.com or 45.54.56.65)
39
40 <li> Range in the form .myhost.net.au <BR>
41 In which case anything that ends with .myhost.net.au will
42 be considered in the range.
43
44 <li> Range in the form ddd.ddd.ddd. <BR>
45 This will be treated as range ddd.ddd.ddd.0 to ddd.ddd.ddd.255.
46 It is not necessary to specify 3 first bytes you can use just
47 one or two. For example 130. will cover address between 130.0.0.0
48 and 13.255.255.255.
49
50 <li> Range in the form host_from[: \t\n\r\f]host_to. <br>
51 That is two hostnames or ips separated by either whitespace
52 or colon.
53 </UL>
54 */
55 public synchronized boolean add(String s){
56 if(s == null) return false;
57
58 s = s.trim();
59 if(s.length() == 0) return false;
60
61 Object[] entry;
62
63 if(s.charAt(s.length()-1) == '.'){
64 //thing like: 111.222.33.
65 //it is being treated as range 111.222.33.000 - 111.222.33.255
66
67 int[] addr = ip2intarray(s);
68 long from,to;
69 from = to = 0;
70
71 if(addr == null) return false;
72 for(int i = 0; i< 4;++i){
73 if(addr[i]>=0)
74 from += (((long)addr[i]) << 8*(3-i));
75 else{
76 to = from;
77 while(i<4)
78 to += 255l << 8*(3-i++);
79 break;
80 }
81 }
82 entry = new Object[] {s,null,new Long(from),new Long(to)};
83 all.addElement(entry);
84
85 }else if(s.charAt(0) == '.'){
86 //Thing like: .myhost.com
87
88 end_names.addElement(s);
89 all.addElement(new Object[]{s,null,null,null});
90 }else{
91 StringTokenizer tokens = new StringTokenizer(s," \t\r\n\f:");
92 if(tokens.countTokens() > 1){
93 entry = new Object[] {s,null,null,null};
94 resolve(entry,tokens.nextToken(),tokens.nextToken());
95 all.addElement(entry);
96 }else{
97 entry = new Object[] {s,null,null,null};
98 all.addElement(entry);
99 host_names.put(s,entry);
100 resolve(entry);
101 }
102
103 }
104
105 return true;
106 }
107
108 /**
109 * Adds another ip for this range.
110 @param ip IP os the host which should be added to this range.
111 */
112 public synchronized void add(InetAddress ip){
113 long from, to;
114 from = to = ip2long(ip);
115 all.addElement(new Object[]{ip.getHostName(),ip,new Long(from),
116 new Long(to)});
117 }
118
119 /**
120 * Adds another range of ips for this range.Any host with ip address
121 greater than or equal to the address of from and smaller than or equal
122 to the address of to will be included in the range.
123 @param from IP from where range starts(including).
124 @param to IP where range ends(including).
125 */
126 public synchronized void add(InetAddress from,InetAddress to){
127 all.addElement(new Object[]{from.getHostAddress()+":"+to.getHostAddress()
128 ,null,new Long(ip2long(from)),
129 new Long(ip2long(to))});
130 }
131
132 /**
133 * Checks wether the givan host is in the range. Attempts to resolve
134 host name if required.
135 @param host Host name to check.
136 @return true If host is in the range, false otherwise.
137 * @see InetRange#contains(String,boolean)
138 */
139 public synchronized boolean contains(String host){
140 return contains(host,true);
141 }
142
143 /**
144 * Checks wether the given host is in the range.
145 * <P>
146 * Algorithm: <BR>
147 * <ol>
148 * <li>Look up if the hostname is in the range (in the Hashtable).
149 * <li>Check if it ends with one of the speciefied endings.
150 * <li>Check if it is ip(eg.130.220.35.98). If it is check if it is
151 * in the range.
152 * <li>If attemptResolve is true, host is name, rather than ip, and
153 * all previous attempts failed, try to resolve the hostname, and
154 * check wether the ip associated with the host is in the range.It
155 * also repeats all previos steps with the hostname obtained from
156 * InetAddress, but the name is not allways the full name,it is
157 * quite likely to be the same. Well it was on my machine.
158 * </ol>
159 @param host Host name to check.
160 @param attemptResolve Wether to lookup ip address which corresponds
161 to the host,if required.
162 @return true If host is in the range, false otherwise.
163 */
164 public synchronized boolean contains(String host,boolean attemptResolve){
165 if(all.size() ==0) return false; //Empty range
166
167 host = host.trim();
168 if(host.length() == 0) return false;
169
170 if(checkHost(host)) return true;
171 if(checkHostEnding(host)) return true;
172
173 long l = host2long(host);
174 if(l >=0) return contains(l);
175
176 if(!attemptResolve) return false;
177
178 try{
179 InetAddress ip = InetAddress.getByName(host);
180 return contains(ip);
181 }catch(UnknownHostException uhe){
182
183 }
184
185 return false;
186 }
187
188 /**
189 * Checks wether the given ip is in the range.
190 @param ip Address of the host to check.
191 @return true If host is in the range, false otherwise.
192 */
193 public synchronized boolean contains(InetAddress ip){
194 if(checkHostEnding(ip.getHostName())) return true;
195 if(checkHost(ip.getHostName())) return true;
196 return contains(ip2long(ip));
197 }
198 /**
199 Get all entries in the range as strings. <BR>
200 These strings can be used to delete entries from the range
201 with remove function.
202 @return Array of entries as strings.
203 @see InetRange#remove(String)
204 */
205 public synchronized String[] getAll(){
206 int size = all.size();
207 Object entry[];
208 String all_names[] = new String[size];
209
210 for(int i=0;i<size;++i){
211 entry = (Object[]) all.elementAt(i);
212 all_names[i] = (String) entry[0];
213 }
214 return all_names;
215 }
216 /**
217 Removes an entry from this range.<BR>
218 @param s Entry to remove.
219 @return true if successfull.
220 */
221 public synchronized boolean remove(String s){
222 Enumeration eEnum = all.elements();
223 while(eEnum.hasMoreElements()){
224 Object[] entry = (Object[]) eEnum.nextElement();
225 if(s.equals(entry[0])){
226 all.removeElement(entry);
227 end_names.removeElement(s);
228 host_names.remove(s);
229 return true;
230 }
231 }
232 return false;
233 }
234
235 /** Get string representaion of this Range.*/
236 public String toString(){
237 String all[] = getAll();
238 if(all.length == 0) return "";
239
240 String s = all[0];
241 for(int i=1;i<all.length;++i)
242 s += "; "+all[i];
243 return s;
244 }
245
246 /** Creates a clone of this Object*/
247 public Object clone(){
248 InetRange new_range = new InetRange();
249 new_range.all = (Vector)all.clone();
250 new_range.end_names = (Vector) end_names.clone();
251 new_range.host_names = (Hashtable)host_names.clone();
252 return new_range;
253 }
254
255
256 //Private methods
257 /////////////////
258 /**
259 * Same as previous but used internally, to avoid
260 * unnecessary convertion of IPs, when checking subranges
261 */
262 private synchronized boolean contains(long ip){
263 Enumeration eEnum = all.elements();
264 while(eEnum.hasMoreElements()){
265 Object[] obj = (Object[]) eEnum.nextElement();
266 Long from = obj[2]==null?null:(Long)obj[2];
267 Long to = obj[3]==null?null:(Long)obj[3];
268 if(from != null && from.longValue()<= ip
269 && to.longValue() >= ip) return true;
270
271 }
272 return false;
273 }
274
275 private boolean checkHost(String host){
276 return host_names.containsKey(host);
277 }
278 private boolean checkHostEnding(String host){
279 Enumeration eEnum = end_names.elements();
280 while(eEnum.hasMoreElements()){
281 if(host.endsWith((String) eEnum.nextElement())) return true;
282 }
283 return false;
284 }
285 private void resolve(Object[] entry){
286 //First check if it's in the form ddd.ddd.ddd.ddd.
287 long ip = host2long((String) entry[0]);
288 if(ip >= 0){
289 entry[2] = entry[3] = new Long(ip);
290 }else{
291 InetRangeResolver res = new InetRangeResolver(entry);
292 res.resolve(useSeparateThread);
293 }
294 }
295 private void resolve(Object[] entry,String from,String to){
296 long f,t;
297 if((f=host2long(from))>= 0 && (t=host2long(to)) >= 0){
298 entry[2] = new Long(f);
299 entry[3] = new Long(t);
300 }else{
301 InetRangeResolver res = new InetRangeResolver(entry,from,to);
302 res.resolve(useSeparateThread);
303 }
304 }
305
306
307
308 //Class methods
309 ///////////////
310
311 //Converts ipv4 to long value(unsigned int)
312 ///////////////////////////////////////////
313 static long ip2long(InetAddress ip){
314 long l=0;
315 byte[] addr = ip.getAddress();
316
317 if(addr.length ==4){ //IPV4
318 for(int i=0;i<4;++i)
319 l += (((long)addr[i] &0xFF) << 8*(3-i));
320 }else{ //IPV6
321 return 0; //Have no idea how to deal with those
322 }
323 return l;
324 }
325
326
327 long host2long(String host){
328 long ip=0;
329
330 //check if it's ddd.ddd.ddd.ddd
331 if(!Character.isDigit(host.charAt(0))) return -1;
332
333 int[] addr = ip2intarray(host);
334 if(addr == null) return -1;
335
336 for(int i=0;i<addr.length;++i)
337 ip += ((long)(addr[i]>=0 ? addr[i] : 0)) << 8*(3-i);
338
339 return ip;
340 }
341
342 static int[] ip2intarray(String host){
343 int[] address = {-1,-1,-1,-1};
344 int i=0;
345 StringTokenizer tokens = new StringTokenizer(host,".");
346 if(tokens.countTokens() > 4) return null;
347 while(tokens.hasMoreTokens()){
348 try{
349 address[i++] = Integer.parseInt(tokens.nextToken()) & 0xFF;
350 }catch(NumberFormatException nfe){
351 return null;
352 }
353
354 }
355 return address;
356 }
357
358
359 /*
360 //* This was the test main function
361 //**********************************
362
363 public static void main(String args[])throws UnknownHostException{
364 int i;
365
366 InetRange ir = new InetRange();
367
368
369 for(i=0;i<args.length;++i){
370 System.out.println("Adding:" + args[i]);
371 ir.add(args[i]);
372 }
373
374 String host;
375 java.io.DataInputStream din = new java.io.DataInputStream(System.in);
376 try{
377 host = din.readLine();
378 while(host!=null){
379 if(ir.contains(host)){
380 System.out.println("Range contains ip:"+host);
381 }else{
382 System.out.println(host+" is not in the range");
383 }
384 host = din.readLine();
385 }
386 }catch(java.io.IOException io_ex){
387 io_ex.printStackTrace();
388 }
389 }
390 ********************/
391
392 }
393
394
395 class InetRangeResolver implements Runnable{
396
397 Object[] entry;
398
399 String from, to;
400
401 InetRangeResolver(Object[] entry){
402 this.entry = entry;
403 from = to = null;
404 }
405 InetRangeResolver(Object[] entry,String from,String to){
406 this.entry = entry;
407 this.from = from;
408 this.to = to;
409 }
410 public final void resolve(){
411 resolve(true);
412 }
413 public final void resolve(boolean inSeparateThread){
414 if(inSeparateThread){
415 Thread t = new Thread(this);
416 t.start();
417 }else
418 run();
419
420 }
421 public void run(){
422 try{
423 if(from == null){
424 InetAddress ip = InetAddress.getByName((String) entry[0]);
425 entry[1] = ip;
426 Long l = new Long(InetRange.ip2long(ip));
427 entry[2] = entry[3] = l;
428 }else{
429 InetAddress f = InetAddress.getByName(from);
430 InetAddress t = InetAddress.getByName(to);
431 entry[2] = new Long(InetRange.ip2long(f));
432 entry[3] = new Long(InetRange.ip2long(t));
433
434 }
435 }catch(UnknownHostException uhe){
436 //System.err.println("Resolve failed for "+from+','+to+','+entry[0]);
437 }
438 }
439
440 }