• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.net;
18 
19 import com.google.common.annotations.Beta;
20 import com.google.common.base.MoreObjects;
21 import com.google.common.base.Preconditions;
22 import com.google.common.hash.Hashing;
23 import com.google.common.io.ByteStreams;
24 import com.google.common.primitives.Ints;
25 
26 import java.net.Inet4Address;
27 import java.net.Inet6Address;
28 import java.net.InetAddress;
29 import java.net.UnknownHostException;
30 import java.nio.ByteBuffer;
31 import java.util.Arrays;
32 
33 import javax.annotation.Nullable;
34 
35 /**
36  * Static utility methods pertaining to {@link InetAddress} instances.
37  *
38  * <p><b>Important note:</b> Unlike {@code InetAddress.getByName()}, the
39  * methods of this class never cause DNS services to be accessed. For
40  * this reason, you should prefer these methods as much as possible over
41  * their JDK equivalents whenever you are expecting to handle only
42  * IP address string literals -- there is no blocking DNS penalty for a
43  * malformed string.
44  *
45  * <p>When dealing with {@link Inet4Address} and {@link Inet6Address}
46  * objects as byte arrays (vis. {@code InetAddress.getAddress()}) they
47  * are 4 and 16 bytes in length, respectively, and represent the address
48  * in network byte order.
49  *
50  * <p>Examples of IP addresses and their byte representations:
51  * <ul>
52  * <li>The IPv4 loopback address, {@code "127.0.0.1"}.<br/>
53  *     {@code 7f 00 00 01}
54  *
55  * <li>The IPv6 loopback address, {@code "::1"}.<br/>
56  *     {@code 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01}
57  *
58  * <li>From the IPv6 reserved documentation prefix ({@code 2001:db8::/32}),
59  *     {@code "2001:db8::1"}.<br/>
60  *     {@code 20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 01}
61  *
62  * <li>An IPv6 "IPv4 compatible" (or "compat") address,
63  *     {@code "::192.168.0.1"}.<br/>
64  *     {@code 00 00 00 00 00 00 00 00 00 00 00 00 c0 a8 00 01}
65  *
66  * <li>An IPv6 "IPv4 mapped" address, {@code "::ffff:192.168.0.1"}.<br/>
67  *     {@code 00 00 00 00 00 00 00 00 00 00 ff ff c0 a8 00 01}
68  * </ul>
69  *
70  * <p>A few notes about IPv6 "IPv4 mapped" addresses and their observed
71  * use in Java.
72  * <br><br>
73  * "IPv4 mapped" addresses were originally a representation of IPv4
74  * addresses for use on an IPv6 socket that could receive both IPv4
75  * and IPv6 connections (by disabling the {@code IPV6_V6ONLY} socket
76  * option on an IPv6 socket).  Yes, it's confusing.  Nevertheless,
77  * these "mapped" addresses were never supposed to be seen on the
78  * wire.  That assumption was dropped, some say mistakenly, in later
79  * RFCs with the apparent aim of making IPv4-to-IPv6 transition simpler.
80  *
81  * <p>Technically one <i>can</i> create a 128bit IPv6 address with the wire
82  * format of a "mapped" address, as shown above, and transmit it in an
83  * IPv6 packet header.  However, Java's InetAddress creation methods
84  * appear to adhere doggedly to the original intent of the "mapped"
85  * address: all "mapped" addresses return {@link Inet4Address} objects.
86  *
87  * <p>For added safety, it is common for IPv6 network operators to filter
88  * all packets where either the source or destination address appears to
89  * be a "compat" or "mapped" address.  Filtering suggestions usually
90  * recommend discarding any packets with source or destination addresses
91  * in the invalid range {@code ::/3}, which includes both of these bizarre
92  * address formats.  For more information on "bogons", including lists
93  * of IPv6 bogon space, see:
94  *
95  * <ul>
96  * <li><a target="_parent"
97  *        href="http://en.wikipedia.org/wiki/Bogon_filtering"
98  *       >http://en.wikipedia.org/wiki/Bogon_filtering</a>
99  * <li><a target="_parent"
100  *        href="http://www.cymru.com/Bogons/ipv6.txt"
101  *       >http://www.cymru.com/Bogons/ipv6.txt</a>
102  * <li><a target="_parent"
103  *        href="http://www.cymru.com/Bogons/v6bogon.html"
104  *       >http://www.cymru.com/Bogons/v6bogon.html</a>
105  * <li><a target="_parent"
106  *        href="http://www.space.net/~gert/RIPE/ipv6-filters.html"
107  *       >http://www.space.net/~gert/RIPE/ipv6-filters.html</a>
108  * </ul>
109  *
110  * @author Erik Kline
111  * @since 5.0
112  */
113 @Beta
114 public final class InetAddresses {
115   private static final int IPV4_PART_COUNT = 4;
116   private static final int IPV6_PART_COUNT = 8;
117   private static final Inet4Address LOOPBACK4 = (Inet4Address) forString("127.0.0.1");
118   private static final Inet4Address ANY4 = (Inet4Address) forString("0.0.0.0");
119 
InetAddresses()120   private InetAddresses() {}
121 
122   /**
123    * Returns an {@link Inet4Address}, given a byte array representation of the IPv4 address.
124    *
125    * @param bytes byte array representing an IPv4 address (should be of length 4)
126    * @return {@link Inet4Address} corresponding to the supplied byte array
127    * @throws IllegalArgumentException if a valid {@link Inet4Address} can not be created
128    */
getInet4Address(byte[] bytes)129   private static Inet4Address getInet4Address(byte[] bytes) {
130     Preconditions.checkArgument(bytes.length == 4,
131         "Byte array has invalid length for an IPv4 address: %s != 4.",
132         bytes.length);
133 
134     // Given a 4-byte array, this cast should always succeed.
135     return (Inet4Address) bytesToInetAddress(bytes);
136   }
137 
138   /**
139    * Returns the {@link InetAddress} having the given string representation.
140    *
141    * <p>This deliberately avoids all nameservice lookups (e.g. no DNS).
142    *
143    * @param ipString {@code String} containing an IPv4 or IPv6 string literal, e.g.
144    *     {@code "192.168.0.1"} or {@code "2001:db8::1"}
145    * @return {@link InetAddress} representing the argument
146    * @throws IllegalArgumentException if the argument is not a valid IP string literal
147    */
forString(String ipString)148   public static InetAddress forString(String ipString) {
149     byte[] addr = ipStringToBytes(ipString);
150 
151     // The argument was malformed, i.e. not an IP string literal.
152     if (addr == null) {
153       throw new IllegalArgumentException(
154           String.format("'%s' is not an IP string literal.", ipString));
155     }
156 
157     return bytesToInetAddress(addr);
158   }
159 
160   /**
161    * Returns {@code true} if the supplied string is a valid IP string
162    * literal, {@code false} otherwise.
163    *
164    * @param ipString {@code String} to evaluated as an IP string literal
165    * @return {@code true} if the argument is a valid IP string literal
166    */
isInetAddress(String ipString)167   public static boolean isInetAddress(String ipString) {
168     return ipStringToBytes(ipString) != null;
169   }
170 
ipStringToBytes(String ipString)171   private static byte[] ipStringToBytes(String ipString) {
172     // Make a first pass to categorize the characters in this string.
173     boolean hasColon = false;
174     boolean hasDot = false;
175     for (int i = 0; i < ipString.length(); i++) {
176       char c = ipString.charAt(i);
177       if (c == '.') {
178         hasDot = true;
179       } else if (c == ':') {
180         if (hasDot) {
181           return null;  // Colons must not appear after dots.
182         }
183         hasColon = true;
184       } else if (Character.digit(c, 16) == -1) {
185         return null;  // Everything else must be a decimal or hex digit.
186       }
187     }
188 
189     // Now decide which address family to parse.
190     if (hasColon) {
191       if (hasDot) {
192         ipString = convertDottedQuadToHex(ipString);
193         if (ipString == null) {
194           return null;
195         }
196       }
197       return textToNumericFormatV6(ipString);
198     } else if (hasDot) {
199       return textToNumericFormatV4(ipString);
200     }
201     return null;
202   }
203 
textToNumericFormatV4(String ipString)204   private static byte[] textToNumericFormatV4(String ipString) {
205     String[] address = ipString.split("\\.", IPV4_PART_COUNT + 1);
206     if (address.length != IPV4_PART_COUNT) {
207       return null;
208     }
209 
210     byte[] bytes = new byte[IPV4_PART_COUNT];
211     try {
212       for (int i = 0; i < bytes.length; i++) {
213         bytes[i] = parseOctet(address[i]);
214       }
215     } catch (NumberFormatException ex) {
216       return null;
217     }
218 
219     return bytes;
220   }
221 
textToNumericFormatV6(String ipString)222   private static byte[] textToNumericFormatV6(String ipString) {
223     // An address can have [2..8] colons, and N colons make N+1 parts.
224     String[] parts = ipString.split(":", IPV6_PART_COUNT + 2);
225     if (parts.length < 3 || parts.length > IPV6_PART_COUNT + 1) {
226       return null;
227     }
228 
229     // Disregarding the endpoints, find "::" with nothing in between.
230     // This indicates that a run of zeroes has been skipped.
231     int skipIndex = -1;
232     for (int i = 1; i < parts.length - 1; i++) {
233       if (parts[i].length() == 0) {
234         if (skipIndex >= 0) {
235           return null;  // Can't have more than one ::
236         }
237         skipIndex = i;
238       }
239     }
240 
241     int partsHi;  // Number of parts to copy from above/before the "::"
242     int partsLo;  // Number of parts to copy from below/after the "::"
243     if (skipIndex >= 0) {
244       // If we found a "::", then check if it also covers the endpoints.
245       partsHi = skipIndex;
246       partsLo = parts.length - skipIndex - 1;
247       if (parts[0].length() == 0 && --partsHi != 0) {
248         return null;  // ^: requires ^::
249       }
250       if (parts[parts.length - 1].length() == 0 && --partsLo != 0) {
251         return null;  // :$ requires ::$
252       }
253     } else {
254       // Otherwise, allocate the entire address to partsHi.  The endpoints
255       // could still be empty, but parseHextet() will check for that.
256       partsHi = parts.length;
257       partsLo = 0;
258     }
259 
260     // If we found a ::, then we must have skipped at least one part.
261     // Otherwise, we must have exactly the right number of parts.
262     int partsSkipped = IPV6_PART_COUNT - (partsHi + partsLo);
263     if (!(skipIndex >= 0 ? partsSkipped >= 1 : partsSkipped == 0)) {
264       return null;
265     }
266 
267     // Now parse the hextets into a byte array.
268     ByteBuffer rawBytes = ByteBuffer.allocate(2 * IPV6_PART_COUNT);
269     try {
270       for (int i = 0; i < partsHi; i++) {
271         rawBytes.putShort(parseHextet(parts[i]));
272       }
273       for (int i = 0; i < partsSkipped; i++) {
274         rawBytes.putShort((short) 0);
275       }
276       for (int i = partsLo; i > 0; i--) {
277         rawBytes.putShort(parseHextet(parts[parts.length - i]));
278       }
279     } catch (NumberFormatException ex) {
280       return null;
281     }
282     return rawBytes.array();
283   }
284 
convertDottedQuadToHex(String ipString)285   private static String convertDottedQuadToHex(String ipString) {
286     int lastColon = ipString.lastIndexOf(':');
287     String initialPart = ipString.substring(0, lastColon + 1);
288     String dottedQuad = ipString.substring(lastColon + 1);
289     byte[] quad = textToNumericFormatV4(dottedQuad);
290     if (quad == null) {
291       return null;
292     }
293     String penultimate = Integer.toHexString(((quad[0] & 0xff) << 8) | (quad[1] & 0xff));
294     String ultimate = Integer.toHexString(((quad[2] & 0xff) << 8) | (quad[3] & 0xff));
295     return initialPart + penultimate + ":" + ultimate;
296   }
297 
parseOctet(String ipPart)298   private static byte parseOctet(String ipPart) {
299     // Note: we already verified that this string contains only hex digits.
300     int octet = Integer.parseInt(ipPart);
301     // Disallow leading zeroes, because no clear standard exists on
302     // whether these should be interpreted as decimal or octal.
303     if (octet > 255 || (ipPart.startsWith("0") && ipPart.length() > 1)) {
304       throw new NumberFormatException();
305     }
306     return (byte) octet;
307   }
308 
parseHextet(String ipPart)309   private static short parseHextet(String ipPart) {
310     // Note: we already verified that this string contains only hex digits.
311     int hextet = Integer.parseInt(ipPart, 16);
312     if (hextet > 0xffff) {
313       throw new NumberFormatException();
314     }
315     return (short) hextet;
316   }
317 
318   /**
319    * Convert a byte array into an InetAddress.
320    *
321    * {@link InetAddress#getByAddress} is documented as throwing a checked
322    * exception "if IP address if of illegal length."  We replace it with
323    * an unchecked exception, for use by callers who already know that addr
324    * is an array of length 4 or 16.
325    *
326    * @param addr the raw 4-byte or 16-byte IP address in big-endian order
327    * @return an InetAddress object created from the raw IP address
328    */
bytesToInetAddress(byte[] addr)329   private static InetAddress bytesToInetAddress(byte[] addr) {
330     try {
331       return InetAddress.getByAddress(addr);
332     } catch (UnknownHostException e) {
333       throw new AssertionError(e);
334     }
335   }
336 
337   /**
338    * Returns the string representation of an {@link InetAddress}.
339    *
340    * <p>For IPv4 addresses, this is identical to
341    * {@link InetAddress#getHostAddress()}, but for IPv6 addresses, the output
342    * follows <a href="http://tools.ietf.org/html/rfc5952">RFC 5952</a>
343    * section 4.  The main difference is that this method uses "::" for zero
344    * compression, while Java's version uses the uncompressed form.
345    *
346    * <p>This method uses hexadecimal for all IPv6 addresses, including
347    * IPv4-mapped IPv6 addresses such as "::c000:201".  The output does not
348    * include a Scope ID.
349    *
350    * @param ip {@link InetAddress} to be converted to an address string
351    * @return {@code String} containing the text-formatted IP address
352    * @since 10.0
353    */
toAddrString(InetAddress ip)354   public static String toAddrString(InetAddress ip) {
355     Preconditions.checkNotNull(ip);
356     if (ip instanceof Inet4Address) {
357       // For IPv4, Java's formatting is good enough.
358       return ip.getHostAddress();
359     }
360     Preconditions.checkArgument(ip instanceof Inet6Address);
361     byte[] bytes = ip.getAddress();
362     int[] hextets = new int[IPV6_PART_COUNT];
363     for (int i = 0; i < hextets.length; i++) {
364       hextets[i] = Ints.fromBytes(
365           (byte) 0, (byte) 0, bytes[2 * i], bytes[2 * i + 1]);
366     }
367     compressLongestRunOfZeroes(hextets);
368     return hextetsToIPv6String(hextets);
369   }
370 
371   /**
372    * Identify and mark the longest run of zeroes in an IPv6 address.
373    *
374    * <p>Only runs of two or more hextets are considered.  In case of a tie, the
375    * leftmost run wins.  If a qualifying run is found, its hextets are replaced
376    * by the sentinel value -1.
377    *
378    * @param hextets {@code int[]} mutable array of eight 16-bit hextets
379    */
compressLongestRunOfZeroes(int[] hextets)380   private static void compressLongestRunOfZeroes(int[] hextets) {
381     int bestRunStart = -1;
382     int bestRunLength = -1;
383     int runStart = -1;
384     for (int i = 0; i < hextets.length + 1; i++) {
385       if (i < hextets.length && hextets[i] == 0) {
386         if (runStart < 0) {
387           runStart = i;
388         }
389       } else if (runStart >= 0) {
390         int runLength = i - runStart;
391         if (runLength > bestRunLength) {
392           bestRunStart = runStart;
393           bestRunLength = runLength;
394         }
395         runStart = -1;
396       }
397     }
398     if (bestRunLength >= 2) {
399       Arrays.fill(hextets, bestRunStart, bestRunStart + bestRunLength, -1);
400     }
401   }
402 
403   /**
404    * Convert a list of hextets into a human-readable IPv6 address.
405    *
406    * <p>In order for "::" compression to work, the input should contain negative
407    * sentinel values in place of the elided zeroes.
408    *
409    * @param hextets {@code int[]} array of eight 16-bit hextets, or -1s
410    */
hextetsToIPv6String(int[] hextets)411   private static String hextetsToIPv6String(int[] hextets) {
412     /*
413      * While scanning the array, handle these state transitions:
414      *   start->num => "num"     start->gap => "::"
415      *   num->num   => ":num"    num->gap   => "::"
416      *   gap->num   => "num"     gap->gap   => ""
417      */
418     StringBuilder buf = new StringBuilder(39);
419     boolean lastWasNumber = false;
420     for (int i = 0; i < hextets.length; i++) {
421       boolean thisIsNumber = hextets[i] >= 0;
422       if (thisIsNumber) {
423         if (lastWasNumber) {
424           buf.append(':');
425         }
426         buf.append(Integer.toHexString(hextets[i]));
427       } else {
428         if (i == 0 || lastWasNumber) {
429           buf.append("::");
430         }
431       }
432       lastWasNumber = thisIsNumber;
433     }
434     return buf.toString();
435   }
436 
437   /**
438    * Returns the string representation of an {@link InetAddress} suitable
439    * for inclusion in a URI.
440    *
441    * <p>For IPv4 addresses, this is identical to
442    * {@link InetAddress#getHostAddress()}, but for IPv6 addresses it
443    * compresses zeroes and surrounds the text with square brackets; for example
444    * {@code "[2001:db8::1]"}.
445    *
446    * <p>Per section 3.2.2 of
447    * <a target="_parent"
448    *    href="http://tools.ietf.org/html/rfc3986#section-3.2.2"
449    *  >http://tools.ietf.org/html/rfc3986</a>,
450    * a URI containing an IPv6 string literal is of the form
451    * {@code "http://[2001:db8::1]:8888/index.html"}.
452    *
453    * <p>Use of either {@link InetAddresses#toAddrString},
454    * {@link InetAddress#getHostAddress()}, or this method is recommended over
455    * {@link InetAddress#toString()} when an IP address string literal is
456    * desired.  This is because {@link InetAddress#toString()} prints the
457    * hostname and the IP address string joined by a "/".
458    *
459    * @param ip {@link InetAddress} to be converted to URI string literal
460    * @return {@code String} containing URI-safe string literal
461    */
toUriString(InetAddress ip)462   public static String toUriString(InetAddress ip) {
463     if (ip instanceof Inet6Address) {
464       return "[" + toAddrString(ip) + "]";
465     }
466     return toAddrString(ip);
467   }
468 
469   /**
470    * Returns an InetAddress representing the literal IPv4 or IPv6 host
471    * portion of a URL, encoded in the format specified by RFC 3986 section 3.2.2.
472    *
473    * <p>This function is similar to {@link InetAddresses#forString(String)},
474    * however, it requires that IPv6 addresses are surrounded by square brackets.
475    *
476    * <p>This function is the inverse of
477    * {@link InetAddresses#toUriString(java.net.InetAddress)}.
478    *
479    * @param hostAddr A RFC 3986 section 3.2.2 encoded IPv4 or IPv6 address
480    * @return an InetAddress representing the address in {@code hostAddr}
481    * @throws IllegalArgumentException if {@code hostAddr} is not a valid
482    *     IPv4 address, or IPv6 address surrounded by square brackets
483    */
forUriString(String hostAddr)484   public static InetAddress forUriString(String hostAddr) {
485     Preconditions.checkNotNull(hostAddr);
486 
487     // Decide if this should be an IPv6 or IPv4 address.
488     String ipString;
489     int expectBytes;
490     if (hostAddr.startsWith("[") && hostAddr.endsWith("]")) {
491       ipString = hostAddr.substring(1, hostAddr.length() - 1);
492       expectBytes = 16;
493     } else {
494       ipString = hostAddr;
495       expectBytes = 4;
496     }
497 
498     // Parse the address, and make sure the length/version is correct.
499     byte[] addr = ipStringToBytes(ipString);
500     if (addr == null || addr.length != expectBytes) {
501       throw new IllegalArgumentException(
502           String.format("Not a valid URI IP literal: '%s'", hostAddr));
503     }
504 
505     return bytesToInetAddress(addr);
506   }
507 
508   /**
509    * Returns {@code true} if the supplied string is a valid URI IP string
510    * literal, {@code false} otherwise.
511    *
512    * @param ipString {@code String} to evaluated as an IP URI host string literal
513    * @return {@code true} if the argument is a valid IP URI host
514    */
isUriInetAddress(String ipString)515   public static boolean isUriInetAddress(String ipString) {
516     try {
517       forUriString(ipString);
518       return true;
519     } catch (IllegalArgumentException e) {
520       return false;
521     }
522   }
523 
524   /**
525    * Evaluates whether the argument is an IPv6 "compat" address.
526    *
527    * <p>An "IPv4 compatible", or "compat", address is one with 96 leading
528    * bits of zero, with the remaining 32 bits interpreted as an
529    * IPv4 address.  These are conventionally represented in string
530    * literals as {@code "::192.168.0.1"}, though {@code "::c0a8:1"} is
531    * also considered an IPv4 compatible address (and equivalent to
532    * {@code "::192.168.0.1"}).
533    *
534    * <p>For more on IPv4 compatible addresses see section 2.5.5.1 of
535    * <a target="_parent"
536    *    href="http://tools.ietf.org/html/rfc4291#section-2.5.5.1"
537    *    >http://tools.ietf.org/html/rfc4291</a>
538    *
539    * <p>NOTE: This method is different from
540    * {@link Inet6Address#isIPv4CompatibleAddress} in that it more
541    * correctly classifies {@code "::"} and {@code "::1"} as
542    * proper IPv6 addresses (which they are), NOT IPv4 compatible
543    * addresses (which they are generally NOT considered to be).
544    *
545    * @param ip {@link Inet6Address} to be examined for embedded IPv4 compatible address format
546    * @return {@code true} if the argument is a valid "compat" address
547    */
isCompatIPv4Address(Inet6Address ip)548   public static boolean isCompatIPv4Address(Inet6Address ip) {
549     if (!ip.isIPv4CompatibleAddress()) {
550       return false;
551     }
552 
553     byte[] bytes = ip.getAddress();
554     if ((bytes[12] == 0) && (bytes[13] == 0) && (bytes[14] == 0)
555         && ((bytes[15] == 0) || (bytes[15] == 1))) {
556       return false;
557     }
558 
559     return true;
560   }
561 
562   /**
563    * Returns the IPv4 address embedded in an IPv4 compatible address.
564    *
565    * @param ip {@link Inet6Address} to be examined for an embedded IPv4 address
566    * @return {@link Inet4Address} of the embedded IPv4 address
567    * @throws IllegalArgumentException if the argument is not a valid IPv4 compatible address
568    */
getCompatIPv4Address(Inet6Address ip)569   public static Inet4Address getCompatIPv4Address(Inet6Address ip) {
570     Preconditions.checkArgument(isCompatIPv4Address(ip),
571         "Address '%s' is not IPv4-compatible.", toAddrString(ip));
572 
573     return getInet4Address(Arrays.copyOfRange(ip.getAddress(), 12, 16));
574   }
575 
576   /**
577    * Evaluates whether the argument is a 6to4 address.
578    *
579    * <p>6to4 addresses begin with the {@code "2002::/16"} prefix.
580    * The next 32 bits are the IPv4 address of the host to which
581    * IPv6-in-IPv4 tunneled packets should be routed.
582    *
583    * <p>For more on 6to4 addresses see section 2 of
584    * <a target="_parent" href="http://tools.ietf.org/html/rfc3056#section-2"
585    *    >http://tools.ietf.org/html/rfc3056</a>
586    *
587    * @param ip {@link Inet6Address} to be examined for 6to4 address format
588    * @return {@code true} if the argument is a 6to4 address
589    */
is6to4Address(Inet6Address ip)590   public static boolean is6to4Address(Inet6Address ip) {
591     byte[] bytes = ip.getAddress();
592     return (bytes[0] == (byte) 0x20) && (bytes[1] == (byte) 0x02);
593   }
594 
595   /**
596    * Returns the IPv4 address embedded in a 6to4 address.
597    *
598    * @param ip {@link Inet6Address} to be examined for embedded IPv4 in 6to4 address
599    * @return {@link Inet4Address} of embedded IPv4 in 6to4 address
600    * @throws IllegalArgumentException if the argument is not a valid IPv6 6to4 address
601    */
get6to4IPv4Address(Inet6Address ip)602   public static Inet4Address get6to4IPv4Address(Inet6Address ip) {
603     Preconditions.checkArgument(is6to4Address(ip),
604         "Address '%s' is not a 6to4 address.", toAddrString(ip));
605 
606     return getInet4Address(Arrays.copyOfRange(ip.getAddress(), 2, 6));
607   }
608 
609   /**
610    * A simple immutable data class to encapsulate the information to be found in a
611    * Teredo address.
612    *
613    * <p>All of the fields in this class are encoded in various portions
614    * of the IPv6 address as part of the protocol.  More protocols details
615    * can be found at:
616    * <a target="_parent" href="http://en.wikipedia.org/wiki/Teredo_tunneling"
617    *    >http://en.wikipedia.org/wiki/Teredo_tunneling</a>.
618    *
619    * <p>The RFC can be found here:
620    * <a target="_parent" href="http://tools.ietf.org/html/rfc4380"
621    *    >http://tools.ietf.org/html/rfc4380</a>.
622    *
623    * @since 5.0
624    */
625   @Beta
626   public static final class TeredoInfo {
627     private final Inet4Address server;
628     private final Inet4Address client;
629     private final int port;
630     private final int flags;
631 
632     /**
633      * Constructs a TeredoInfo instance.
634      *
635      * <p>Both server and client can be {@code null}, in which case the
636      * value {@code "0.0.0.0"} will be assumed.
637      *
638      * @throws IllegalArgumentException if either of the {@code port} or the {@code flags}
639      *     arguments are out of range of an unsigned short
640      */
641     // TODO: why is this public?
TeredoInfo( @ullable Inet4Address server, @Nullable Inet4Address client, int port, int flags)642     public TeredoInfo(
643         @Nullable Inet4Address server, @Nullable Inet4Address client, int port, int flags) {
644       Preconditions.checkArgument((port >= 0) && (port <= 0xffff),
645           "port '%s' is out of range (0 <= port <= 0xffff)", port);
646       Preconditions.checkArgument((flags >= 0) && (flags <= 0xffff),
647           "flags '%s' is out of range (0 <= flags <= 0xffff)", flags);
648 
649       this.server = MoreObjects.firstNonNull(server, ANY4);
650       this.client = MoreObjects.firstNonNull(client, ANY4);
651       this.port = port;
652       this.flags = flags;
653     }
654 
getServer()655     public Inet4Address getServer() {
656       return server;
657     }
658 
getClient()659     public Inet4Address getClient() {
660       return client;
661     }
662 
getPort()663     public int getPort() {
664       return port;
665     }
666 
getFlags()667     public int getFlags() {
668       return flags;
669     }
670   }
671 
672   /**
673    * Evaluates whether the argument is a Teredo address.
674    *
675    * <p>Teredo addresses begin with the {@code "2001::/32"} prefix.
676    *
677    * @param ip {@link Inet6Address} to be examined for Teredo address format
678    * @return {@code true} if the argument is a Teredo address
679    */
isTeredoAddress(Inet6Address ip)680   public static boolean isTeredoAddress(Inet6Address ip) {
681     byte[] bytes = ip.getAddress();
682     return (bytes[0] == (byte) 0x20) && (bytes[1] == (byte) 0x01)
683            && (bytes[2] == 0) && (bytes[3] == 0);
684   }
685 
686   /**
687    * Returns the Teredo information embedded in a Teredo address.
688    *
689    * @param ip {@link Inet6Address} to be examined for embedded Teredo information
690    * @return extracted {@code TeredoInfo}
691    * @throws IllegalArgumentException if the argument is not a valid IPv6 Teredo address
692    */
getTeredoInfo(Inet6Address ip)693   public static TeredoInfo getTeredoInfo(Inet6Address ip) {
694     Preconditions.checkArgument(isTeredoAddress(ip),
695         "Address '%s' is not a Teredo address.", toAddrString(ip));
696 
697     byte[] bytes = ip.getAddress();
698     Inet4Address server = getInet4Address(Arrays.copyOfRange(bytes, 4, 8));
699 
700     int flags = ByteStreams.newDataInput(bytes, 8).readShort() & 0xffff;
701 
702     // Teredo obfuscates the mapped client port, per section 4 of the RFC.
703     int port = ~ByteStreams.newDataInput(bytes, 10).readShort() & 0xffff;
704 
705     byte[] clientBytes = Arrays.copyOfRange(bytes, 12, 16);
706     for (int i = 0; i < clientBytes.length; i++) {
707       // Teredo obfuscates the mapped client IP, per section 4 of the RFC.
708       clientBytes[i] = (byte) ~clientBytes[i];
709     }
710     Inet4Address client = getInet4Address(clientBytes);
711 
712     return new TeredoInfo(server, client, port, flags);
713   }
714 
715   /**
716    * Evaluates whether the argument is an ISATAP address.
717    *
718    * <p>From RFC 5214: "ISATAP interface identifiers are constructed in
719    * Modified EUI-64 format [...] by concatenating the 24-bit IANA OUI
720    * (00-00-5E), the 8-bit hexadecimal value 0xFE, and a 32-bit IPv4
721    * address in network byte order [...]"
722    *
723    * <p>For more on ISATAP addresses see section 6.1 of
724    * <a target="_parent" href="http://tools.ietf.org/html/rfc5214#section-6.1"
725    *    >http://tools.ietf.org/html/rfc5214</a>
726    *
727    * @param ip {@link Inet6Address} to be examined for ISATAP address format
728    * @return {@code true} if the argument is an ISATAP address
729    */
isIsatapAddress(Inet6Address ip)730   public static boolean isIsatapAddress(Inet6Address ip) {
731 
732     // If it's a Teredo address with the right port (41217, or 0xa101)
733     // which would be encoded as 0x5efe then it can't be an ISATAP address.
734     if (isTeredoAddress(ip)) {
735       return false;
736     }
737 
738     byte[] bytes = ip.getAddress();
739 
740     if ((bytes[8] | (byte) 0x03) != (byte) 0x03) {
741 
742       // Verify that high byte of the 64 bit identifier is zero, modulo
743       // the U/L and G bits, with which we are not concerned.
744       return false;
745     }
746 
747     return (bytes[9] == (byte) 0x00) && (bytes[10] == (byte) 0x5e)
748            && (bytes[11] == (byte) 0xfe);
749   }
750 
751   /**
752    * Returns the IPv4 address embedded in an ISATAP address.
753    *
754    * @param ip {@link Inet6Address} to be examined for embedded IPv4 in ISATAP address
755    * @return {@link Inet4Address} of embedded IPv4 in an ISATAP address
756    * @throws IllegalArgumentException if the argument is not a valid IPv6 ISATAP address
757    */
getIsatapIPv4Address(Inet6Address ip)758   public static Inet4Address getIsatapIPv4Address(Inet6Address ip) {
759     Preconditions.checkArgument(isIsatapAddress(ip),
760         "Address '%s' is not an ISATAP address.", toAddrString(ip));
761 
762     return getInet4Address(Arrays.copyOfRange(ip.getAddress(), 12, 16));
763   }
764 
765   /**
766    * Examines the Inet6Address to determine if it is an IPv6 address of one
767    * of the specified address types that contain an embedded IPv4 address.
768    *
769    * <p>NOTE: ISATAP addresses are explicitly excluded from this method
770    * due to their trivial spoofability.  With other transition addresses
771    * spoofing involves (at least) infection of one's BGP routing table.
772    *
773    * @param ip {@link Inet6Address} to be examined for embedded IPv4 client address
774    * @return {@code true} if there is an embedded IPv4 client address
775    * @since 7.0
776    */
hasEmbeddedIPv4ClientAddress(Inet6Address ip)777   public static boolean hasEmbeddedIPv4ClientAddress(Inet6Address ip) {
778     return isCompatIPv4Address(ip) || is6to4Address(ip) || isTeredoAddress(ip);
779   }
780 
781   /**
782    * Examines the Inet6Address to extract the embedded IPv4 client address
783    * if the InetAddress is an IPv6 address of one of the specified address
784    * types that contain an embedded IPv4 address.
785    *
786    * <p>NOTE: ISATAP addresses are explicitly excluded from this method
787    * due to their trivial spoofability.  With other transition addresses
788    * spoofing involves (at least) infection of one's BGP routing table.
789    *
790    * @param ip {@link Inet6Address} to be examined for embedded IPv4 client address
791    * @return {@link Inet4Address} of embedded IPv4 client address
792    * @throws IllegalArgumentException if the argument does not have a valid embedded IPv4 address
793    */
getEmbeddedIPv4ClientAddress(Inet6Address ip)794   public static Inet4Address getEmbeddedIPv4ClientAddress(Inet6Address ip) {
795     if (isCompatIPv4Address(ip)) {
796       return getCompatIPv4Address(ip);
797     }
798 
799     if (is6to4Address(ip)) {
800       return get6to4IPv4Address(ip);
801     }
802 
803     if (isTeredoAddress(ip)) {
804       return getTeredoInfo(ip).getClient();
805     }
806 
807     throw new IllegalArgumentException(
808         String.format("'%s' has no embedded IPv4 address.", toAddrString(ip)));
809   }
810 
811   /**
812    * Evaluates whether the argument is an "IPv4 mapped" IPv6 address.
813    *
814    * <p>An "IPv4 mapped" address is anything in the range ::ffff:0:0/96
815    * (sometimes written as ::ffff:0.0.0.0/96), with the last 32 bits
816    * interpreted as an IPv4 address.
817    *
818    * <p>For more on IPv4 mapped addresses see section 2.5.5.2 of
819    * <a target="_parent"
820    *    href="http://tools.ietf.org/html/rfc4291#section-2.5.5.2"
821    *    >http://tools.ietf.org/html/rfc4291</a>
822    *
823    * <p>Note: This method takes a {@code String} argument because
824    * {@link InetAddress} automatically collapses mapped addresses to IPv4.
825    * (It is actually possible to avoid this using one of the obscure
826    * {@link Inet6Address} methods, but it would be unwise to depend on such
827    * a poorly-documented feature.)
828    *
829    * @param ipString {@code String} to be examined for embedded IPv4-mapped IPv6 address format
830    * @return {@code true} if the argument is a valid "mapped" address
831    * @since 10.0
832    */
isMappedIPv4Address(String ipString)833   public static boolean isMappedIPv4Address(String ipString) {
834     byte[] bytes = ipStringToBytes(ipString);
835     if (bytes != null && bytes.length == 16) {
836       for (int i = 0; i < 10; i++) {
837         if (bytes[i] != 0) {
838           return false;
839         }
840       }
841       for (int i = 10; i < 12; i++) {
842         if (bytes[i] != (byte) 0xff) {
843           return false;
844         }
845       }
846       return true;
847     }
848     return false;
849   }
850 
851   /**
852    * Coerces an IPv6 address into an IPv4 address.
853    *
854    * <p>HACK: As long as applications continue to use IPv4 addresses for
855    * indexing into tables, accounting, et cetera, it may be necessary to
856    * <b>coerce</b> IPv6 addresses into IPv4 addresses. This function does
857    * so by hashing the upper 64 bits into {@code 224.0.0.0/3}
858    * (64 bits into 29 bits).
859    *
860    * <p>A "coerced" IPv4 address is equivalent to itself.
861    *
862    * <p>NOTE: This function is failsafe for security purposes: ALL IPv6
863    * addresses (except localhost (::1)) are hashed to avoid the security
864    * risk associated with extracting an embedded IPv4 address that might
865    * permit elevated privileges.
866    *
867    * @param ip {@link InetAddress} to "coerce"
868    * @return {@link Inet4Address} represented "coerced" address
869    * @since 7.0
870    */
getCoercedIPv4Address(InetAddress ip)871   public static Inet4Address getCoercedIPv4Address(InetAddress ip) {
872     if (ip instanceof Inet4Address) {
873       return (Inet4Address) ip;
874     }
875 
876     // Special cases:
877     byte[] bytes = ip.getAddress();
878     boolean leadingBytesOfZero = true;
879     for (int i = 0; i < 15; ++i) {
880       if (bytes[i] != 0) {
881         leadingBytesOfZero = false;
882         break;
883       }
884     }
885     if (leadingBytesOfZero && (bytes[15] == 1)) {
886       return LOOPBACK4;  // ::1
887     } else if (leadingBytesOfZero && (bytes[15] == 0)) {
888       return ANY4;  // ::0
889     }
890 
891     Inet6Address ip6 = (Inet6Address) ip;
892     long addressAsLong = 0;
893     if (hasEmbeddedIPv4ClientAddress(ip6)) {
894       addressAsLong = getEmbeddedIPv4ClientAddress(ip6).hashCode();
895     } else {
896 
897       // Just extract the high 64 bits (assuming the rest is user-modifiable).
898       addressAsLong = ByteBuffer.wrap(ip6.getAddress(), 0, 8).getLong();
899     }
900 
901     // Many strategies for hashing are possible.  This might suffice for now.
902     int coercedHash = Hashing.murmur3_32().hashLong(addressAsLong).asInt();
903 
904     // Squash into 224/4 Multicast and 240/4 Reserved space (i.e. 224/3).
905     coercedHash |= 0xe0000000;
906 
907     // Fixup to avoid some "illegal" values.  Currently the only potential
908     // illegal value is 255.255.255.255.
909     if (coercedHash == 0xffffffff) {
910       coercedHash = 0xfffffffe;
911     }
912 
913     return getInet4Address(Ints.toByteArray(coercedHash));
914   }
915 
916   /**
917    * Returns an integer representing an IPv4 address regardless of
918    * whether the supplied argument is an IPv4 address or not.
919    *
920    * <p>IPv6 addresses are <b>coerced</b> to IPv4 addresses before being
921    * converted to integers.
922    *
923    * <p>As long as there are applications that assume that all IP addresses
924    * are IPv4 addresses and can therefore be converted safely to integers
925    * (for whatever purpose) this function can be used to handle IPv6
926    * addresses as well until the application is suitably fixed.
927    *
928    * <p>NOTE: an IPv6 address coerced to an IPv4 address can only be used
929    * for such purposes as rudimentary identification or indexing into a
930    * collection of real {@link InetAddress}es.  They cannot be used as
931    * real addresses for the purposes of network communication.
932    *
933    * @param ip {@link InetAddress} to convert
934    * @return {@code int}, "coerced" if ip is not an IPv4 address
935    * @since 7.0
936    */
coerceToInteger(InetAddress ip)937   public static int coerceToInteger(InetAddress ip) {
938     return ByteStreams.newDataInput(getCoercedIPv4Address(ip).getAddress()).readInt();
939   }
940 
941   /**
942    * Returns an Inet4Address having the integer value specified by
943    * the argument.
944    *
945    * @param address {@code int}, the 32bit integer address to be converted
946    * @return {@link Inet4Address} equivalent of the argument
947    */
fromInteger(int address)948   public static Inet4Address fromInteger(int address) {
949     return getInet4Address(Ints.toByteArray(address));
950   }
951 
952   /**
953    * Returns an address from a <b>little-endian ordered</b> byte array
954    * (the opposite of what {@link InetAddress#getByAddress} expects).
955    *
956    * <p>IPv4 address byte array must be 4 bytes long and IPv6 byte array
957    * must be 16 bytes long.
958    *
959    * @param addr the raw IP address in little-endian byte order
960    * @return an InetAddress object created from the raw IP address
961    * @throws UnknownHostException if IP address is of illegal length
962    */
fromLittleEndianByteArray(byte[] addr)963   public static InetAddress fromLittleEndianByteArray(byte[] addr) throws UnknownHostException {
964     byte[] reversed = new byte[addr.length];
965     for (int i = 0; i < addr.length; i++) {
966       reversed[i] = addr[addr.length - i - 1];
967     }
968     return InetAddress.getByAddress(reversed);
969   }
970 
971   /**
972    * Returns a new InetAddress that is one less than the passed in address.
973    * This method works for both IPv4 and IPv6 addresses.
974    *
975    * @param address the InetAddress to decrement
976    * @return a new InetAddress that is one less than the passed in address
977    * @throws IllegalArgumentException if InetAddress is at the beginning of its range
978    * @since 18.0
979    */
decrement(InetAddress address)980   public static InetAddress decrement(InetAddress address) {
981     byte[] addr = address.getAddress();
982     int i = addr.length - 1;
983     while (i >= 0 && addr[i] == (byte) 0x00) {
984       addr[i] = (byte) 0xff;
985       i--;
986     }
987 
988     Preconditions.checkArgument(i >= 0, "Decrementing %s would wrap.", address);
989 
990     addr[i]--;
991     return bytesToInetAddress(addr);
992   }
993 
994   /**
995    * Returns a new InetAddress that is one more than the passed in address.
996    * This method works for both IPv4 and IPv6 addresses.
997    *
998    * @param address the InetAddress to increment
999    * @return a new InetAddress that is one more than the passed in address
1000    * @throws IllegalArgumentException if InetAddress is at the end of its range
1001    * @since 10.0
1002    */
increment(InetAddress address)1003   public static InetAddress increment(InetAddress address) {
1004     byte[] addr = address.getAddress();
1005     int i = addr.length - 1;
1006     while (i >= 0 && addr[i] == (byte) 0xff) {
1007       addr[i] = 0;
1008       i--;
1009     }
1010 
1011     Preconditions.checkArgument(i >= 0, "Incrementing %s would wrap.", address);
1012 
1013     addr[i]++;
1014     return bytesToInetAddress(addr);
1015   }
1016 
1017   /**
1018    * Returns true if the InetAddress is either 255.255.255.255 for IPv4 or
1019    * ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff for IPv6.
1020    *
1021    * @return true if the InetAddress is either 255.255.255.255 for IPv4 or
1022    *     ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff for IPv6
1023    * @since 10.0
1024    */
isMaximum(InetAddress address)1025   public static boolean isMaximum(InetAddress address) {
1026     byte[] addr = address.getAddress();
1027     for (int i = 0; i < addr.length; i++) {
1028       if (addr[i] != (byte) 0xff) {
1029         return false;
1030       }
1031     }
1032     return true;
1033   }
1034 }
1035