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 gnu.java.lang.CPStringBuilder;
042
043 import java.util.Arrays;
044 import java.io.ObjectInputStream;
045 import java.io.ObjectOutputStream;
046 import java.io.IOException;
047
048 /*
049 * Written using on-line Java Platform 1.4 API Specification and
050 * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt)
051 *
052 * @author Michael Koch
053 * @status Updated to 1.5. Serialization compatibility is tested.
054 */
055 public final class Inet6Address extends InetAddress
056 {
057 static final long serialVersionUID = 6880410070516793377L;
058
059 /**
060 * Needed for serialization
061 */
062 byte[] ipaddress;
063
064 /**
065 * The scope ID, if any.
066 * @since 1.5
067 * @serial
068 */
069 private int scope_id;
070
071 /**
072 * The scope ID, if any.
073 * @since 1.5
074 * @serial
075 */
076 private boolean scope_id_set;
077
078 /**
079 * Whether ifname is set or not.
080 * @since 1.5
081 * @serial
082 */
083 private boolean scope_ifname_set;
084
085 /**
086 * Name of the network interface, used only by the serialization methods
087 * @since 1.5
088 * @serial
089 */
090 private String ifname;
091
092 /**
093 * Scope network interface, or <code>null</code>.
094 */
095 private transient NetworkInterface nif;
096
097 /**
098 * The address family of these addresses (used for serialization).
099 */
100 private static final int AF_INET6 = 10;
101
102 /**
103 * Create an Inet6Address object
104 *
105 * @param addr The IP address
106 * @param host The hostname
107 */
108 Inet6Address(byte[] addr, String host)
109 {
110 super(addr, host, AF_INET6);
111 // Super constructor clones the addr. Get a reference to the clone.
112 this.ipaddress = this.addr;
113 ifname = null;
114 scope_ifname_set = scope_id_set = false;
115 scope_id = 0;
116 nif = null;
117 }
118
119 /**
120 * Utility routine to check if the InetAddress is an IP multicast address
121 *
122 * @since 1.1
123 */
124 public boolean isMulticastAddress()
125 {
126 return ipaddress[0] == (byte) 0xFF;
127 }
128
129 /**
130 * Utility routine to check if the InetAddress in a wildcard address
131 *
132 * @since 1.4
133 */
134 public boolean isAnyLocalAddress()
135 {
136 byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
137
138 return Arrays.equals(ipaddress, anylocal);
139 }
140
141 /**
142 * Utility routine to check if the InetAddress is a loopback address
143 *
144 * @since 1.4
145 */
146 public boolean isLoopbackAddress()
147 {
148 byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
149
150 return Arrays.equals(ipaddress, loopback);
151 }
152
153 /**
154 * Utility routine to check if the InetAddress is an link local address
155 *
156 * @since 1.4
157 */
158 public boolean isLinkLocalAddress()
159 {
160 return ipaddress[0] == 0xFA;
161 }
162
163 /**
164 * Utility routine to check if the InetAddress is a site local address
165 *
166 * @since 1.4
167 */
168 public boolean isSiteLocalAddress()
169 {
170 return ipaddress[0] == 0xFB;
171 }
172
173 /**
174 * Utility routine to check if the multicast address has global scope
175 *
176 * @since 1.4
177 */
178 public boolean isMCGlobal()
179 {
180 if (! isMulticastAddress())
181 return false;
182
183 return (ipaddress[1] & 0x0F) == 0xE;
184 }
185
186 /**
187 * Utility routine to check if the multicast address has node scope
188 *
189 * @since 1.4
190 */
191 public boolean isMCNodeLocal()
192 {
193 if (! isMulticastAddress())
194 return false;
195
196 return (ipaddress[1] & 0x0F) == 0x1;
197 }
198
199 /**
200 * Utility routine to check if the multicast address has link scope
201 *
202 * @since 1.4
203 */
204 public boolean isMCLinkLocal()
205 {
206 if (! isMulticastAddress())
207 return false;
208
209 return (ipaddress[1] & 0x0F) == 0x2;
210 }
211
212 /**
213 * Utility routine to check if the multicast address has site scope
214 *
215 * @since 1.4
216 */
217 public boolean isMCSiteLocal()
218 {
219 if (! isMulticastAddress())
220 return false;
221
222 return (ipaddress[1] & 0x0F) == 0x5;
223 }
224
225 /**
226 * Utility routine to check if the multicast address has organization scope
227 *
228 * @since 1.4
229 */
230 public boolean isMCOrgLocal()
231 {
232 if (! isMulticastAddress())
233 return false;
234
235 return (ipaddress[1] & 0x0F) == 0x8;
236 }
237
238 /**
239 * Returns the raw IP address of this InetAddress object. The result is in
240 * network byte order: the highest order byte of the address is i
241 * n getAddress()[0]
242 */
243 public byte[] getAddress()
244 {
245 return (byte[]) ipaddress.clone();
246 }
247
248 /**
249 * Creates a scoped Inet6Address where the scope has an integer id.
250 *
251 * @throws UnkownHostException if the address is an invalid number of bytes.
252 * @since 1.5
253 */
254 public static Inet6Address getByAddress(String host, byte[] addr,
255 int scopeId)
256 throws UnknownHostException
257 {
258 if( addr.length != 16 )
259 throw new UnknownHostException("Illegal address length: " + addr.length
260 + " bytes.");
261 Inet6Address ip = new Inet6Address( addr, host );
262 ip.scope_id = scopeId;
263 ip.scope_id_set = true;
264 return ip;
265 }
266
267 /**
268 * Creates a scoped Inet6Address where the scope is a given
269 * NetworkInterface.
270 *
271 * @throws UnkownHostException if the address is an invalid number of bytes.
272 * @since 1.5
273 */
274 public static Inet6Address getByAddress(String host, byte[] addr,
275 NetworkInterface nif)
276 throws UnknownHostException
277 {
278 if( addr.length != 16 )
279 throw new UnknownHostException("Illegal address length: " + addr.length
280 + " bytes.");
281 Inet6Address ip = new Inet6Address( addr, host );
282 ip.nif = nif;
283
284 return ip;
285 }
286
287 /**
288 * Returns the <code>NetworkInterface</code> of the address scope
289 * if it is a scoped address and the scope is given in the form of a
290 * NetworkInterface.
291 * (I.e. the address was created using the
292 * getByAddress(String, byte[], NetworkInterface) method)
293 * Otherwise this method returns <code>null</code>.
294 * @since 1.5
295 */
296 public NetworkInterface getScopedInterface()
297 {
298 return nif;
299 }
300
301 /**
302 * Returns the scope ID of the address scope if it is a scoped adress using
303 * an integer to identify the scope.
304 *
305 * Otherwise this method returns 0.
306 * @since 1.5
307 */
308 public int getScopeId()
309 {
310 // check scope_id_set because some JDK-serialized objects seem to have
311 // scope_id set to a nonzero value even when scope_id_set == false
312 if( scope_id_set )
313 return scope_id;
314 return 0;
315 }
316
317 /**
318 * Returns the IP address string in textual presentation
319 */
320 public String getHostAddress()
321 {
322 CPStringBuilder sbuf = new CPStringBuilder(40);
323
324 for (int i = 0; i < 16; i += 2)
325 {
326 int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF);
327
328 if (i > 0)
329 sbuf.append(':');
330
331 sbuf.append(Integer.toHexString(x));
332 }
333 if( nif != null )
334 sbuf.append( "%" + nif.getName() );
335 else if( scope_id_set )
336 sbuf.append( "%" + scope_id );
337
338 return sbuf.toString();
339 }
340
341 /**
342 * Returns a hashcode for this IP address
343 * (The hashcode is independent of scope)
344 */
345 public int hashCode()
346 {
347 return super.hashCode();
348 }
349
350 /**
351 * Compares this object against the specified object
352 */
353 public boolean equals(Object obj)
354 {
355 if (! (obj instanceof Inet6Address))
356 return false;
357
358 Inet6Address ip = (Inet6Address)obj;
359 if (ipaddress.length != ip.ipaddress.length)
360 return false;
361
362 for (int i = 0; i < ip.ipaddress.length; i++)
363 if (ipaddress[i] != ip.ipaddress[i])
364 return false;
365
366 if( ip.nif != null && nif != null )
367 return nif.equals( ip.nif );
368 if( ip.nif != nif )
369 return false;
370 if( ip.scope_id_set != scope_id_set )
371 return false;
372 if( scope_id_set )
373 return (scope_id == ip.scope_id);
374 return true;
375 }
376
377 /**
378 * Utility routine to check if the InetAddress is an
379 * IPv4 compatible IPv6 address
380 *
381 * @since 1.4
382 */
383 public boolean isIPv4CompatibleAddress()
384 {
385 if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00
386 || ipaddress[3] != 0x00 || ipaddress[4] != 0x00
387 || ipaddress[5] != 0x00 || ipaddress[6] != 0x00
388 || ipaddress[7] != 0x00 || ipaddress[8] != 0x00
389 || ipaddress[9] != 0x00 || ipaddress[10] != 0x00
390 || ipaddress[11] != 0x00)
391 return false;
392
393 return true;
394 }
395
396 /**
397 * Required for 1.5-compatible serialization.
398 * @since 1.5
399 */
400 private void readObject(ObjectInputStream s)
401 throws IOException, ClassNotFoundException
402 {
403 s.defaultReadObject();
404 try
405 {
406 if( scope_ifname_set )
407 nif = NetworkInterface.getByName( ifname );
408 }
409 catch( SocketException se )
410 {
411 // FIXME: Ignore this? or throw an IOException?
412 }
413 }
414
415 /**
416 * Required for 1.5-compatible serialization.
417 * @since 1.5
418 */
419 private void writeObject(ObjectOutputStream s)
420 throws IOException
421 {
422 if( nif != null )
423 {
424 ifname = nif.getName();
425 scope_ifname_set = true;
426 }
427 s.defaultWriteObject();
428 }
429 }