source: trunk/gcc/libjava/java/net/InetAddress.java

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 16.3 KB
Line 
1// INetAddress.java -- An Internet Protocol (IP) address.
2
3/* Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11package java.net;
12
13import java.io.ObjectInputStream;
14import java.io.ObjectOutputStream;
15import java.io.IOException;
16import java.io.Serializable;
17import java.io.ObjectStreamException;
18
19/**
20 * @author Per Bothner
21 * @date January 6, 1999.
22 */
23
24/*
25 * Written using on-line Java Platform 1.2 API Specification, as well
26 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
27 * (The latter turns out to have some errors ...)
28 * Status: Believed complete and correct.
29 *
30 * @specnote This class is not final since JK 1.4
31 */
32
33public class InetAddress implements Serializable
34{
35 // The Serialized Form specifies that an int 'address' is saved/restored.
36 // This class uses a byte array internally so we'll just do the conversion
37 // at serialization time and leave the rest of the algorithm as is.
38 private int address;
39 transient byte[] addr;
40 String hostName;
41 // The field 'family' seems to be the AF_ value.
42 // FIXME: Much of the code in the other java.net classes does not make
43 // use of this family field. A better implementation would be to make
44 // use of getaddrinfo() and have other methods just check the family
45 // field rather than examining the length of the address each time.
46 int family;
47 private static final long serialVersionUID = 3286316764910316507L;
48
49 /**
50 * Needed for serialization
51 */
52 private void readResolve () throws ObjectStreamException
53 {
54 // FIXME: implement this
55 }
56
57 private void readObject(ObjectInputStream ois)
58 throws IOException, ClassNotFoundException
59 {
60 ois.defaultReadObject();
61 addr = new byte[4];
62 addr[3] = (byte) address;
63 for (int i = 2; i >= 0; --i)
64 addr[i] = (byte) (address >>= 8);
65 // Ignore family from serialized data. Since the saved address is 32 bits
66 // the deserialized object will have an IPv4 address i.e. AF_INET family.
67 // FIXME: An alternative is to call the aton method on the deserialized
68 // hostname to get a new address. The Serialized Form doc is silent
69 // on how these fields are used.
70 family = getFamily (addr);
71 }
72
73 private void writeObject(ObjectOutputStream oos) throws IOException
74 {
75 // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
76 // or a 16 byte IPv6 address.
77 int len = addr.length;
78 int i = len - 4;
79 for (; i < len; i++)
80 address = address << 8 | (((int) addr[i]) & 0xFF);
81 oos.defaultWriteObject();
82 }
83
84 private static native int getFamily (byte[] address);
85
86 InetAddress (byte[] address, String hostname)
87 {
88 addr = address;
89 hostName = hostname;
90 if (address != null)
91 family = getFamily (address);
92 }
93
94 /**
95 * Utility routine to check if the InetAddress is an IP multicast address
96 *
97 * @since 1.1
98 */
99 public boolean isMulticastAddress ()
100 {
101 int len = addr.length;
102 if (len == 4)
103 return (addr[0] & 0xF0) == 0xE0;
104 if (len == 16)
105 return addr[0] == (byte) 0xFF;
106 return false;
107 }
108
109 /**
110 * Utility routine to check if the InetAddress in a wildcard address
111 *
112 * @since 1.4
113 */
114 public boolean isAnyLocalAddress ()
115 {
116 // This is the IPv4 implementation.
117 // Any class derived from InetAddress should override this.
118 return addr == zeros;
119 }
120
121 /**
122 * Utility routine to check if the InetAddress is a loopback address
123 *
124 * @since 1.4
125 */
126 public boolean isLoopbackAddress ()
127 {
128 // This is the IPv4 implementation.
129 // Any class derived from InetAddress should override this.
130
131 return addr[0] == 0x7F;
132 }
133
134 /**
135 * Utility routine to check if InetAddress is a link local address
136 *
137 * @since 1.4
138 */
139 public boolean isLinkLocalAddress ()
140 {
141 // This is the IPv4 implementation.
142 // Any class derived from InetAddress should override this.
143
144 // XXX: This seems to not exist with IPv4 addresses
145 return false;
146 }
147
148 /**
149 * Utility routine to check if InetAddress is a site local address
150 *
151 * @since 1.4
152 */
153 public boolean isSiteLocalAddress ()
154 {
155 // This is the IPv4 implementation.
156 // Any class derived from InetAddress should override this.
157
158 // 10.0.0.0/8
159 if (addr[0] == 0x0A)
160 return true;
161
162 // XXX: Suns JDK 1.4.1 (on Linux) seems to have a bug here:
163 // it says 172.16.0.0 - 172.255.255.255 are site local addresses
164
165 // 172.16.0.0/12
166 if (addr[0] == 0xAC && (addr[1] & 0xF0) == 0x01)
167 return true;
168
169 // 192.168.0.0/16
170 if (addr[0] == 0xC0 && addr[1] == 0xA8)
171 return true;
172
173 // XXX: Do we need to check more addresses here ?
174 return false;
175 }
176
177 /**
178 * Utility routine to check if InetAddress is a global multicast address
179 *
180 * @since 1.4
181 */
182 public boolean isMCGlobal ()
183 {
184 // This is the IPv4 implementation.
185 // Any class derived from InetAddress should override this.
186
187 // XXX: This seems to not exist with IPv4 addresses
188 return false;
189 }
190
191 /**
192 * Utility reoutine to check if InetAddress is a node local multicast address
193 *
194 * @since 1.4
195 */
196 public boolean isMCNodeLocal ()
197 {
198 // This is the IPv4 implementation.
199 // Any class derived from InetAddress should override this.
200
201 // XXX: This seems to not exist with IPv4 addresses
202 return false;
203 }
204
205 /**
206 * Utility reoutine to check if InetAddress is a link local multicast address
207 *
208 * @since 1.4
209 */
210 public boolean isMCLinkLocal ()
211 {
212 // This is the IPv4 implementation.
213 // Any class derived from InetAddress should override this.
214
215 if (!isMulticastAddress ())
216 return false;
217
218 return (addr[0] == 0xE0
219 && addr[1] == 0x00
220 && addr[2] == 0x00);
221 }
222
223 /**
224 * Utility reoutine to check if InetAddress is a site local multicast address
225 *
226 * @since 1.4
227 */
228 public boolean isMCSiteLocal ()
229 {
230 // This is the IPv4 implementation.
231 // Any class derived from InetAddress should override this.
232
233 // XXX: This seems to not exist with IPv4 addresses
234 return false;
235 }
236
237 /**
238 * Utility reoutine to check if InetAddress is a organization local
239 * multicast address
240 *
241 * @since 1.4
242 */
243 public boolean isMCOrgLocal ()
244 {
245 // This is the IPv4 implementation.
246 // Any class derived from InetAddress should override this.
247
248 // XXX: This seems to not exist with IPv4 addresses
249 return false;
250 }
251
252 /**
253 * Returns the hostname represented by this InetAddress
254 */
255 public String getHostName ()
256 {
257 if (hostName == null)
258 lookup (null, this, false);
259
260 return hostName;
261 }
262
263 /**
264 * Returns the canonical hostname represented by this InetAddress
265 *
266 * @since 1.4
267 */
268 public String getCanonicalHostName ()
269 {
270 SecurityManager sm = System.getSecurityManager ();
271 if (sm != null)
272 {
273 try
274 {
275 sm.checkConnect (hostName, -1);
276 }
277 catch (SecurityException e)
278 {
279 return getHostAddress ();
280 }
281 }
282
283 // Try to find the FDQN now
284 InetAddress address = new InetAddress (getAddress (), null);
285 return address.getHostName ();
286 }
287
288 /**
289 * Returns the IP address of this InetAddress as array of bytes
290 */
291 public byte[] getAddress ()
292 {
293 // An experiment shows that JDK1.2 returns a different byte array each
294 // time. This makes sense, in terms of security.
295 return (byte[]) addr.clone();
296 }
297
298 /* Helper function due to a CNI limitation. */
299 private static InetAddress[] allocArray (int count)
300 {
301 return new InetAddress[count];
302 }
303
304 /* Helper function due to a CNI limitation. */
305 private static SecurityException checkConnect (String hostname)
306 {
307 SecurityManager s = System.getSecurityManager();
308 if (s == null)
309 return null;
310 try
311 {
312 s.checkConnect(hostname, -1);
313 return null;
314 }
315 catch (SecurityException ex)
316 {
317 return ex;
318 }
319 }
320
321 /**
322 * Returns the IP address as string
323 *
324 * @since 1.0.2
325 */
326 public String getHostAddress ()
327 {
328 StringBuffer sbuf = new StringBuffer(40);
329 int len = addr.length;
330 int i = 0;
331 if (len == 16)
332 { // An IPv6 address.
333 for (; ; i += 2)
334 {
335 if (i >= 16)
336 return sbuf.toString();
337 int x = ((addr[i] & 0xFF) << 8) | (addr[i+1] & 0xFF);
338 boolean empty = sbuf.length() == 0;
339 if (empty)
340 {
341 if (i == 10 && x == 0xFFFF)
342 { // IPv4-mapped IPv6 address.
343 sbuf.append(":FFFF:");
344 break; // Continue as IPv4 address;
345 }
346 else if (i == 12)
347 { // IPv4-compatible IPv6 address.
348 sbuf.append(':');
349 break; // Continue as IPv4 address.
350 }
351 else if (i > 0)
352 sbuf.append("::");
353 }
354 else
355 sbuf.append(':');
356 if (x != 0 || i >= 14)
357 sbuf.append(Integer.toHexString(x).toUpperCase());
358 }
359 }
360 for ( ; ; )
361 {
362 sbuf.append(addr[i] & 0xFF);
363 i++;
364 if (i == len)
365 break;
366 sbuf.append('.');
367 }
368
369 return sbuf.toString();
370 }
371
372 /**
373 * Returns a hashcode of the InetAddress
374 */
375 public int hashCode()
376 {
377 // There hashing algorithm is not specified, but a simple experiment
378 // shows that it is equal to the address, as a 32-bit big-endian integer.
379 int hash = 0;
380 int len = addr.length;
381 int i = len > 4 ? len - 4 : 0;
382 for ( ; i < len; i++)
383 hash = (hash << 8) | (addr[i] & 0xFF);
384 return hash;
385 }
386
387 /**
388 * Compares the InetAddress object with another one.
389 */
390 public boolean equals (Object obj)
391 {
392 if (obj == null || ! (obj instanceof InetAddress))
393 return false;
394
395 // "The Java Class Libraries" 2nd edition says "If a machine has
396 // multiple names instances of InetAddress for different name of
397 // that same machine are not equal. This is because they have
398 // different host names." This violates the description in the
399 // JDK 1.2 API documentation. A little experimentation
400 // shows that the latter is correct.
401 byte[] addr1 = addr;
402 byte[] addr2 = ((InetAddress) obj).addr;
403 if (addr1.length != addr2.length)
404 return false;
405 for (int i = addr1.length; --i >= 0; )
406 if (addr1[i] != addr2[i])
407 return false;
408 return true;
409 }
410
411 /**
412 * Returns then <code>InetAddress</code> as string
413 */
414 public String toString()
415 {
416 String result;
417 String address = getHostAddress();
418 if (hostName != null)
419 result = hostName + "/" + address;
420 else
421 result = address;
422 return result;
423 }
424
425 /**
426 * Returns an InetAddress object given the raw IP address.
427 *
428 * The argument is in network byte order: the highest order byte of the
429 * address is in getAddress()[0].
430 *
431 * @param addr The IP address to create the InetAddress object from
432 *
433 * @exception UnknownHostException If IP address has illegal length
434 *
435 * @since 1.4
436 */
437 public static InetAddress getByAddress(byte[] addr)
438 throws UnknownHostException
439 {
440 if (addr.length != 4 && addr.length != 16)
441 throw new UnknownHostException ("IP address has illegal length");
442
443 if (addr.length == 4)
444 return new Inet4Address (addr, null);
445
446 return new Inet6Address (addr, null);
447 }
448
449 /**
450 * Creates an InetAddress based on the provided host name and IP address.
451 * No name service is checked for the validity of the address.
452 *
453 * @param host The hostname of the InetAddress object to create
454 * @param addr The IP address to create the InetAddress object from
455 *
456 * @exception UnknownHostException If IP address is of illegal length
457 *
458 * @since 1.4
459 */
460 public static InetAddress getByAddress (String host, byte[] addr)
461 throws UnknownHostException
462 {
463 if (addr.length == 4)
464 return new Inet4Address (addr, host);
465
466 if (addr.length == 16)
467 return new Inet6Address (addr, host);
468
469 throw new UnknownHostException ("IP address has illegal length");
470 }
471
472 /** If host is a valid numeric IP address, return the numeric address.
473 * Otherwise, return null. */
474 private static native byte[] aton (String host);
475
476 private static native InetAddress[] lookup (String hostname,
477 InetAddress addr, boolean all);
478
479 /**
480 * Determines the IP address of a host, given the host's name.
481 *
482 * @exception UnknownHostException If no IP address for the host could
483 * be found
484 * @exception SecurityException If a security manager exists and its
485 * checkConnect method doesn't allow the operation
486 */
487 public static InetAddress getByName (String hostname)
488 throws UnknownHostException
489 {
490 SecurityManager sm = System.getSecurityManager();
491 if (sm != null)
492 sm.checkConnect (hostname, -1);
493
494 // Default to current host if necessary
495 if (hostname == null)
496 return getLocalHost();
497
498 // Assume that the host string is an IP address
499 byte[] address = aton (hostname);
500 if (address != null)
501 {
502 if (address.length == 4)
503 return new Inet4Address (address, null);
504 else if (address.length == 16)
505 {
506 if ((address[10] == 0xFF) && (address[11] == 0xFF))
507 {
508 byte[] ip4addr = new byte[4];
509 ip4addr[0] = address[12];
510 ip4addr[1] = address[13];
511 ip4addr[2] = address[14];
512 ip4addr[3] = address[15];
513 return new Inet4Address (ip4addr, null);
514 }
515 return new Inet6Address (address, null);
516 }
517 else
518 throw new UnknownHostException ("Address has invalid length");
519 }
520
521 // Try to resolve the host by DNS
522 InetAddress[] addresses = getAllByName (hostname);
523 return addresses[0];
524 }
525
526 /**
527 * Given the name of a host, returns an array of its IP addresses,
528 * based on the configured name service on the system.
529 *
530 * @exception UnknownHostException If no IP address for the host could
531 * be found
532 * @exception SecurityException If a security manager exists and its
533 * checkConnect method doesn't allow the operation
534 */
535 public static InetAddress[] getAllByName (String hostname)
536 throws UnknownHostException
537 {
538 SecurityManager sm = System.getSecurityManager();
539 if (sm != null)
540 sm.checkConnect(hostname, -1);
541
542 // Check if hostname is an IP address
543 byte[] address = aton (hostname);
544 if (address != null)
545 {
546 InetAddress[] result = new InetAddress[1];
547 result[0] = new InetAddress(address, null);
548 return result;
549 }
550
551 // Try to resolve the hostname by DNS
552 return lookup (hostname, null, true);
553 }
554
555 static final byte[] zeros = {0,0,0,0};
556
557 /* dummy InetAddress, used to bind socket to any (all) network interfaces */
558 static final InetAddress ANY_IF = new InetAddress(zeros, null);
559
560 private static final byte[] localhostAddress = { 127, 0, 0, 1 };
561
562 private static native String getLocalHostname ();
563
564 private static InetAddress localhost = null;
565
566 /**
567 * Returns the local host
568 *
569 * @exception UnknownHostException If no IP address for the host could
570 * be found
571 */
572 public static InetAddress getLocalHost() throws UnknownHostException
573 {
574 SecurityManager s = System.getSecurityManager();
575 // Experimentation shows that JDK1.2 does cache the result.
576 // However, if there is a security manager, and the cached result
577 // is other than "localhost", we need to check again.
578 if (localhost == null
579 || (s != null && localhost.addr != localhostAddress))
580 getLocalHost(s);
581 return localhost;
582 }
583
584 private static synchronized void getLocalHost(SecurityManager s)
585 throws UnknownHostException
586 {
587 // Check the localhost cache again, now that we've synchronized.
588 if (s == null && localhost != null)
589 return;
590 String hostname = getLocalHostname();
591 if (s != null)
592 {
593 // "The Java Class Libraries" suggests that if the security
594 // manager disallows getting the local host name, then
595 // we use the loopback host.
596 // However, the JDK 1.2 API claims to throw SecurityException,
597 // which seems to suggest SecurityException is *not* caught.
598 // In this case, experimentation shows that former is correct.
599 try
600 {
601 // This is wrong, if the name returned from getLocalHostname()
602 // is not a fully qualified name. FIXME.
603 s.checkConnect(hostname, -1);
604 }
605 catch (SecurityException ex)
606 {
607 hostname = null;
608 }
609 }
610 if (hostname != null)
611 {
612 try
613 {
614 localhost = new InetAddress(null, null);
615 lookup(hostname, localhost, false);
616 }
617 catch (Exception ex)
618 {
619 }
620 }
621 if (localhost == null)
622 localhost = new InetAddress (localhostAddress, "localhost");
623 }
624}
Note: See TracBrowser for help on using the repository browser.