001 /* Inet6Address.java --
002 Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.net;
040
041 import java.util.Arrays;
042 import java.io.ObjectInputStream;
043 import java.io.ObjectOutputStream;
044 import java.io.IOException;
045
046 /*
047 * Written using on-line Java Platform 1.4 API Specification and
048 * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt)
049 *
050 * @author Michael Koch
051 * @status Updated to 1.5. Serialization compatibility is tested.
052 */
053 public final class Inet6Address extends InetAddress
054 {
055 static final long serialVersionUID = 6880410070516793377L;
056
057 /**
058 * Needed for serialization
059 */
060 byte[] ipaddress;
061
062 /**
063 * The scope ID, if any.
064 * @since 1.5
065 * @serial
066 */
067 private int scope_id;
068
069 /**
070 * The scope ID, if any.
071 * @since 1.5
072 * @serial
073 */
074 private boolean scope_id_set;
075
076 /**
077 * Whether ifname is set or not.
078 * @since 1.5
079 * @serial
080 */
081 private boolean scope_ifname_set;
082
083 /**
084 * Name of the network interface, used only by the serialization methods
085 * @since 1.5
086 * @serial
087 */
088 private String ifname;
089
090 /**
091 * Scope network interface, or <code>null</code>.
092 */
093 private transient NetworkInterface nif;
094
095 /**
096 * The address family of these addresses (used for serialization).
097 */
098 private static final int AF_INET6 = 10;
099
100 /**
101 * Create an Inet6Address object
102 *
103 * @param addr The IP address
104 * @param host The hostname
105 */
106 Inet6Address(byte[] addr, String host)
107 {
108 super(addr, host, AF_INET6);
109 // Super constructor clones the addr. Get a reference to the clone.
110 this.ipaddress = this.addr;
111 ifname = null;
112 scope_ifname_set = scope_id_set = false;
113 scope_id = 0;
114 nif = null;
115 }
116
117 /**
118 * Utility routine to check if the InetAddress is an IP multicast address
119 *
120 * @since 1.1
121 */
122 public boolean isMulticastAddress()
123 {
124 return ipaddress[0] == (byte) 0xFF;
125 }
126
127 /**
128 * Utility routine to check if the InetAddress in a wildcard address
129 *
130 * @since 1.4
131 */
132 public boolean isAnyLocalAddress()
133 {
134 byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
135
136 return Arrays.equals(ipaddress, anylocal);
137 }
138
139 /**
140 * Utility routine to check if the InetAddress is a loopback address
141 *
142 * @since 1.4
143 */
144 public boolean isLoopbackAddress()
145 {
146 byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
147
148 return Arrays.equals(ipaddress, loopback);
149 }
150
151 /**
152 * Utility routine to check if the InetAddress is an link local address
153 *
154 * @since 1.4
155 */
156 public boolean isLinkLocalAddress()
157 {
158 return ipaddress[0] == 0xFA;
159 }
160
161 /**
162 * Utility routine to check if the InetAddress is a site local address
163 *
164 * @since 1.4
165 */
166 public boolean isSiteLocalAddress()
167 {
168 return ipaddress[0] == 0xFB;
169 }
170
171 /**
172 * Utility routine to check if the multicast address has global scope
173 *
174 * @since 1.4
175 */
176 public boolean isMCGlobal()
177 {
178 if (! isMulticastAddress())
179 return false;
180
181 return (ipaddress[1] & 0x0F) == 0xE;
182 }
183
184 /**
185 * Utility routine to check if the multicast address has node scope
186 *
187 * @since 1.4
188 */
189 public boolean isMCNodeLocal()
190 {
191 if (! isMulticastAddress())
192 return false;
193
194 return (ipaddress[1] & 0x0F) == 0x1;
195 }
196
197 /**
198 * Utility routine to check if the multicast address has link scope
199 *
200 * @since 1.4
201 */
202 public boolean isMCLinkLocal()
203 {
204 if (! isMulticastAddress())
205 return false;
206
207 return (ipaddress[1] & 0x0F) == 0x2;
208 }
209
210 /**
211 * Utility routine to check if the multicast address has site scope
212 *
213 * @since 1.4
214 */
215 public boolean isMCSiteLocal()
216 {
217 if (! isMulticastAddress())
218 return false;
219
220 return (ipaddress[1] & 0x0F) == 0x5;
221 }
222
223 /**
224 * Utility routine to check if the multicast address has organization scope
225 *
226 * @since 1.4
227 */
228 public boolean isMCOrgLocal()
229 {
230 if (! isMulticastAddress())
231 return false;
232
233 return (ipaddress[1] & 0x0F) == 0x8;
234 }
235
236 /**
237 * Returns the raw IP address of this InetAddress object. The result is in
238 * network byte order: the highest order byte of the address is i
239 * n getAddress()[0]
240 */
241 public byte[] getAddress()
242 {
243 return (byte[]) ipaddress.clone();
244 }
245
246 /**
247 * Creates a scoped Inet6Address where the scope has an integer id.
248 *
249 * @throws UnkownHostException if the address is an invalid number of bytes.
250 * @since 1.5
251 */
252 public static Inet6Address getByAddress(String host, byte[] addr,
253 int scopeId)
254 throws UnknownHostException
255 {
256 if( addr.length != 16 )
257 throw new UnknownHostException("Illegal address length: " + addr.length
258 + " bytes.");
259 Inet6Address ip = new Inet6Address( addr, host );
260 ip.scope_id = scopeId;
261 ip.scope_id_set = true;
262 return ip;
263 }
264
265 /**
266 * Creates a scoped Inet6Address where the scope is a given
267 * NetworkInterface.
268 *
269 * @throws UnkownHostException if the address is an invalid number of bytes.
270 * @since 1.5
271 */
272 public static Inet6Address getByAddress(String host, byte[] addr,
273 NetworkInterface nif)
274 throws UnknownHostException
275 {
276 if( addr.length != 16 )
277 throw new UnknownHostException("Illegal address length: " + addr.length
278 + " bytes.");
279 Inet6Address ip = new Inet6Address( addr, host );
280 ip.nif = nif;
281
282 return ip;
283 }
284
285 /**
286 * Returns the <code>NetworkInterface</code> of the address scope
287 * if it is a scoped address and the scope is given in the form of a
288 * NetworkInterface.
289 * (I.e. the address was created using the
290 * getByAddress(String, byte[], NetworkInterface) method)
291 * Otherwise this method returns <code>null</code>.
292 * @since 1.5
293 */
294 public NetworkInterface getScopedInterface()
295 {
296 return nif;
297 }
298
299 /**
300 * Returns the scope ID of the address scope if it is a scoped adress using
301 * an integer to identify the scope.
302 *
303 * Otherwise this method returns 0.
304 * @since 1.5
305 */
306 public int getScopeId()
307 {
308 // check scope_id_set because some JDK-serialized objects seem to have
309 // scope_id set to a nonzero value even when scope_id_set == false
310 if( scope_id_set )
311 return scope_id;
312 return 0;
313 }
314
315 /**
316 * Returns the IP address string in textual presentation
317 */
318 public String getHostAddress()
319 {
320 StringBuffer sbuf = new StringBuffer(40);
321
322 for (int i = 0; i < 16; i += 2)
323 {
324 int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF);
325
326 if (i > 0)
327 sbuf.append(':');
328
329 sbuf.append(Integer.toHexString(x));
330 }
331 if( nif != null )
332 sbuf.append( "%" + nif.getName() );
333 else if( scope_id_set )
334 sbuf.append( "%" + scope_id );
335
336 return sbuf.toString();
337 }
338
339 /**
340 * Returns a hashcode for this IP address
341 * (The hashcode is independent of scope)
342 */
343 public int hashCode()
344 {
345 return super.hashCode();
346 }
347
348 /**
349 * Compares this object against the specified object
350 */
351 public boolean equals(Object obj)
352 {
353 if (! (obj instanceof Inet6Address))
354 return false;
355
356 Inet6Address ip = (Inet6Address)obj;
357 if (ipaddress.length != ip.ipaddress.length)
358 return false;
359
360 for (int i = 0; i < ip.ipaddress.length; i++)
361 if (ipaddress[i] != ip.ipaddress[i])
362 return false;
363
364 if( ip.nif != null && nif != null )
365 return nif.equals( ip.nif );
366 if( ip.nif != nif )
367 return false;
368 if( ip.scope_id_set != scope_id_set )
369 return false;
370 if( scope_id_set )
371 return (scope_id == ip.scope_id);
372 return true;
373 }
374
375 /**
376 * Utility routine to check if the InetAddress is an
377 * IPv4 compatible IPv6 address
378 *
379 * @since 1.4
380 */
381 public boolean isIPv4CompatibleAddress()
382 {
383 if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00
384 || ipaddress[3] != 0x00 || ipaddress[4] != 0x00
385 || ipaddress[5] != 0x00 || ipaddress[6] != 0x00
386 || ipaddress[7] != 0x00 || ipaddress[8] != 0x00
387 || ipaddress[9] != 0x00 || ipaddress[10] != 0x00
388 || ipaddress[11] != 0x00)
389 return false;
390
391 return true;
392 }
393
394 /**
395 * Required for 1.5-compatible serialization.
396 * @since 1.5
397 */
398 private void readObject(ObjectInputStream s)
399 throws IOException, ClassNotFoundException
400 {
401 s.defaultReadObject();
402 try
403 {
404 if( scope_ifname_set )
405 nif = NetworkInterface.getByName( ifname );
406 }
407 catch( SocketException se )
408 {
409 // FIXME: Ignore this? or throw an IOException?
410 }
411 }
412
413 /**
414 * Required for 1.5-compatible serialization.
415 * @since 1.5
416 */
417 private void writeObject(ObjectOutputStream s)
418 throws IOException
419 {
420 if( nif != null )
421 {
422 ifname = nif.getName();
423 scope_ifname_set = true;
424 }
425 s.defaultWriteObject();
426 }
427 }