1 package net.logAnalyzer.utils;
2
3 import java.io.BufferedReader;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.io.PrintStream;
9 import java.io.StringReader;
10 import java.net.InetAddress;
11 import java.net.Socket;
12 import java.net.UnknownHostException;
13 import java.util.Properties;
14
15 /***
16 * This class implements the "Who Is" resolution for IP addresses (IP v4 and IP
17 * v6). It uses a file based cache if exists to increase resolution speed.
18 * <p>
19 * Beware than the cache file is not updated until you call
20 * {@link WhoIs#saveWhoIsCache()}.
21 * </p>
22 *
23 * @author Karim REFEYTON
24 * @version 0.1
25 */
26 public class WhoIs {
27 /***
28 * Sans réponse.
29 */
30 private static final String NOTFOUND_RESPONSE = "(not found)";
31
32 /***
33 * File name used to save and reload WhoIs cache.
34 */
35 private static final String WHOISCACHE_FILENAME = "whoIsCache.properties";
36
37 /***
38 * WhoIs cache.
39 */
40 private static Properties whoIsCache = null;
41
42 /***
43 * Address to resolve.
44 */
45 private InetAddress address = null;
46
47 /***
48 * WhoIs servers names. List of WhoIs servers :
49 * <ul>
50 * <li><tt>whois.ripe.net</tt>: <a href="http://www.ripe.net">RIPE NCC
51 * (Réseaux IP Européens) </a>– Europe, the Middle East, and Central Asia</li>
52 * <li><tt>ws.arin.net</tt>: <a href="http://www.arin.net">ARIN
53 * (American Registry for Internet Numbers) </a>– North America Region </li>
54 * <li><tt>whois.apnic.net</tt>: <a href="http://www.apnic.net">APNIC
55 * (Asia Pacific Network Information Centre) </a>– Asia/Pacific Region</li>
56 * <li><tt>whois.afrinic.net</tt>: <a
57 * href="http://www.afrinic.net">AfriNIC (African Network Information
58 * Centre) </a>– Africa Region </li>
59 * <li><tt>whois.lacnic.net</tt>: <a href="http://lacnic.net">LACNIC
60 * (Regional Latin-American and Caribbean IP Address Registry) </a>– Latin
61 * America and some Caribbean Islands</li>
62 * </ul>
63 */
64 public static final String[] WHOIS_SERVERS_NAMES = new String[] {
65 "whois.ripe.net", "ws.arin.net", "whois.apnic.net",
66 "whois.afrinic.net", "whois.lacnic.net" };
67
68 /***
69 * WhoIs servers IP.
70 */
71 public static final String[] WHOIS_SERVERS_IP = new String[] {
72 "193.0.0.135", "ws.arin.net", "202.12.29.13", "whois.afrinic.net",
73 "200.160.2.15" };
74
75 /***
76 * Currently used index of WhoIs server. <tt>-1</tt> if the server is
77 * specified to the constructor.
78 */
79 private int whoIsServerIndex = 0;
80
81 /***
82 * WhoIs server name if specified ot the constructor.
83 */
84 private String whoIsServerName = null;
85
86 /***
87 * <tt>true</tt> if the address is a new address.
88 */
89 private boolean isnew = false;
90
91 /***
92 * Constructs a new WhoIs resolution for the specified address. Uses only
93 * known WhoIs servers {@link #WHOIS_SERVERS_NAMES}.
94 *
95 * @param address
96 * Address to resolve.
97 */
98 public WhoIs(String address) throws UnknownHostException {
99 this.address = InetAddress.getByName(address);
100 this.whoIsServerIndex = 0;
101 loadWhoIsCache();
102 getFullResponse();
103 }
104
105 /***
106 * Constructs a new WhoIs resolution for the specified address. Uses first
107 * the specified whoIsServerName and, if not found, the known WhoIs servers
108 * {@link #WHOIS_SERVERS_NAMES}.
109 *
110 * @param address
111 * Address to resolve.
112 * @param whoIsServerName
113 * WhoIs server to use first.
114 */
115 public WhoIs(String address, String whoIsServerName)
116 throws UnknownHostException {
117 this.address = InetAddress.getByName(address);
118 this.whoIsServerIndex = -1;
119 this.whoIsServerName = whoIsServerName;
120 getFullResponse();
121 }
122
123 /***
124 * Adds a resolution to the cache.
125 *
126 * @param response
127 * Reponse to add to cache.
128 */
129 private void addToWhoIsCache(String response) {
130
131 whoIsCache.setProperty(getAddress(), response);
132 }
133
134 /***
135 * Loads WhoIs cache from a file. The file name is
136 * {@link #WHOISCACHE_FILENAME}.
137 */
138 private void loadWhoIsCache() {
139 if (whoIsCache == null) {
140
141 whoIsCache = new Properties();
142 try {
143 whoIsCache.load(new FileInputStream(WHOISCACHE_FILENAME));
144 } catch (IOException ioe) {
145 whoIsCache.clear();
146 }
147 }
148 }
149
150 /***
151 * Saves WhoIs cache to a file. The file name is
152 * {@link #WHOISCACHE_FILENAME}.
153 */
154 public static void saveWhoIsCache() {
155
156 if (whoIsCache != null) {
157 try {
158 whoIsCache.store(new FileOutputStream(WHOISCACHE_FILENAME), "");
159 } catch (IOException ioe) {
160
161 }
162 }
163 }
164
165 /***
166 * Returns the address to resolve.
167 *
168 * @return IP address to resolve in String format.
169 */
170 public String getAddress() {
171 return this.address.getHostAddress();
172 }
173
174 /***
175 * Returns the address to resolve.
176 *
177 * @return IP address to resolve.
178 */
179 public InetAddress getInetAddress() {
180 return this.address;
181 }
182
183 /***
184 * Returns the IP of the server used to resolve the address.
185 *
186 * @return WhoIs server IP.
187 */
188 public String getWhoIsServerIP() {
189 if (whoIsServerIndex == -1) {
190 return whoIsServerName;
191 } else {
192 return WHOIS_SERVERS_IP[whoIsServerIndex];
193 }
194 }
195
196 /***
197 * Returns the name of the server used to resolve the address.
198 *
199 * @return WhoIs server name.
200 */
201 public String getWhoIsServerName() {
202 if (whoIsServerIndex == -1) {
203 return whoIsServerName;
204 } else {
205 return WHOIS_SERVERS_NAMES[whoIsServerIndex];
206 }
207 }
208
209 /***
210 * Returns the full response of the WhoIs server.
211 *
212 * @return Full response.
213 */
214 public String getFullResponse() {
215 String fullResponse = (String) whoIsCache.getProperty(getAddress(),
216 null);
217 if (fullResponse == null || fullResponse.equals("")) {
218 isnew = (fullResponse == null);
219 Socket whoIsSocket = null;
220 try {
221 StringBuffer response = new StringBuffer();
222
223 whoIsSocket = new Socket(getWhoIsServerIP(), 43);
224 BufferedReader input = new BufferedReader(
225 new InputStreamReader(whoIsSocket.getInputStream()));
226 PrintStream output = new PrintStream(whoIsSocket
227 .getOutputStream());
228
229 output.println(getAddress());
230
231 String line;
232 while ((line = input.readLine()) != null) {
233 if (!line.equals("") && !line.startsWith("%")) {
234 response.append(line).append('\n');
235 }
236 }
237 fullResponse = response.toString();
238
239 String netName = getNetName(fullResponse);
240 if (whoIsServerIndex != -1
241 && (netName == null || netName.equals("")
242 || netName.equalsIgnoreCase("IANA-BLK") || netName
243 .equalsIgnoreCase("ARIN-CIDR-BLOCK"))) {
244 if (whoIsServerIndex < WHOIS_SERVERS_NAMES.length - 1) {
245
246 whoIsServerIndex++;
247 fullResponse = null;
248 return getFullResponse();
249 } else if (whoIsServerName != null) {
250
251
252 whoIsServerIndex = -1;
253 fullResponse = NOTFOUND_RESPONSE;
254 } else {
255
256 whoIsServerIndex = 0;
257 fullResponse = NOTFOUND_RESPONSE;
258 }
259 }
260 } catch (IOException ioe) {
261
262
263 fullResponse = NOTFOUND_RESPONSE;
264 } catch (NullPointerException npe) {
265
266
267 fullResponse = NOTFOUND_RESPONSE;
268 } finally {
269
270 if (whoIsSocket != null) {
271 try {
272 whoIsSocket.close();
273 } catch (IOException ioe) {
274
275 whoIsSocket = null;
276 }
277 }
278
279 if (fullResponse != null && !"".equals(fullResponse)) {
280 addToWhoIsCache(fullResponse);
281 }
282 }
283 } else {
284 isnew = false;
285 }
286 return fullResponse;
287 }
288
289 /***
290 * Returns the CIDR address. Looks at <tt>CIDR</tt> or <tt>route</tt>
291 * information.
292 *
293 * @return Orgnization name.
294 */
295 public String getCIDR() {
296 String cidr = getInfo(getFullResponse(),
297 new String[] { "CIDR", "route" });
298 if (cidr != null) {
299 int pos = cidr.indexOf('/');
300 if (pos >= 0) {
301 cidr = cidr.substring(0, pos);
302 }
303 }
304 return cidr;
305 }
306
307 /***
308 * Returns the coutrny. Looks at <tt>coutrny</tt> or <tt>net-name</tt>
309 * information.
310 *
311 * @return Country.
312 */
313 public String getCountry() {
314 return getInfo(getFullResponse(), new String[] { "country" });
315 }
316
317 /***
318 * Returns the network name. Looks at <tt>netname</tt> or
319 * <tt>net-name</tt> information.
320 *
321 * @return Orgnization name.
322 */
323 public String getNetName() {
324 String netName = getInfo(getFullResponse(), new String[] { "netname",
325 "net-name" });
326 return netName;
327 }
328
329 /***
330 * Returns the network name. Looks at <tt>netname</tt> or
331 * <tt>net-name</tt> information.
332 *
333 * @param response
334 * Response to parse.
335 * @return Orgnization name.
336 */
337 public String getNetName(String response) {
338 String netName = getInfo(response,
339 new String[] { "netname", "net-name" });
340 return netName;
341 }
342
343 /***
344 * Returns the organization name. Looks at <tt>org-name</tt> or
345 * <tt>orgname</tt> or the first <tt>descr</tt> information.
346 *
347 * @return Orgnization name.
348 */
349 public String getOrgName() {
350 String orgName = getInfo(getFullResponse(), new String[] { "org-name",
351 "OrgName", "descr" });
352 return orgName;
353 }
354
355 /***
356 * Returns an information from the specified response. Looks at the
357 * specified infos in order. If the first is found, returns the first info
358 * content. Otherwise, if the second is found, returns the second info
359 * content, etc...
360 *
361 * @param response
362 * Response to parse.
363 * @param infos
364 * Infos to search in priority order.
365 * @return Info content if found; <tt>null</tt> otherwise.
366 */
367 private String getInfo(String response, String[] infos) {
368 String infoContent = null;
369 try {
370 BufferedReader reader = new BufferedReader(new StringReader(
371 response));
372 String line = "";
373 boolean mainInfoFound = false;
374 String[] infosContents = new String[infos.length];
375
376
377 while (!mainInfoFound && (line = reader.readLine()) != null) {
378 String ucLine = line.toUpperCase();
379 for (int i = 0; i < infos.length; i++) {
380 if (infosContents[i] == null) {
381 String ucInfo = infos[i].toUpperCase();
382 if (ucLine.startsWith(ucInfo)) {
383
384 infosContents[i] = line.substring(
385 ucLine.indexOf(' ', ucInfo.length()) + 1)
386 .trim();
387 mainInfoFound = (i == 0);
388 }
389 }
390 }
391 }
392 for (int i = 0; infoContent == null && i < infosContents.length; i++) {
393 infoContent = infosContents[i];
394 }
395 reader.close();
396 } catch (IOException ioe) {
397
398 infoContent = null;
399 }
400
401 return infoContent;
402 }
403
404 /***
405 * Returns <tt>true</tt> is a new address (ie if the address was not in
406 * cache).
407 *
408 * @return <tt>true</tt> if it is a new address; <tt>false</tt>
409 * otherwise.
410 */
411 public boolean isNew() {
412 return this.isnew;
413 }
414 }