11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.net;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.VisibleForTesting;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Preconditions;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.io.ByteStreams;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.primitives.Ints;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.net.Inet4Address;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.net.Inet6Address;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.net.InetAddress;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.net.UnknownHostException;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.nio.ByteBuffer;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Static utility methods pertaining to {@link InetAddress} instances.
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Important note:</b> Unlike {@code InetAddress.getByName()}, the
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * methods of this class never cause DNS services to be accessed. For
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * this reason, you should prefer these methods as much as possible over
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * their JDK equivalents whenever you are expecting to handle only
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * IP address string literals -- there is no blocking DNS penalty for a
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * malformed string.
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class hooks into the {@code sun.net.util.IPAddressUtil} class
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * to make use of the {@code textToNumericFormatV4} and
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code textToNumericFormatV6} methods directly as a means to avoid
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * accidentally traversing all nameservices (it can be vitally important
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * to avoid, say, blocking on DNS at times).
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>When dealing with {@link Inet4Address} and {@link Inet6Address}
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * objects as byte arrays (vis. {@code InetAddress.getAddress()}) they
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * are 4 and 16 bytes in length, respectively, and represent the address
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in network byte order.
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Examples of IP addresses and their byte representations:
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <ul>
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>The IPv4 loopback address, {@code "127.0.0.1"}.<br/>
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     {@code 7f 00 00 01}
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>The IPv6 loopback address, {@code "::1"}.<br/>
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     {@code 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01}
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>From the IPv6 reserved documentation prefix ({@code 2001:db8::/32}),
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     {@code "2001:db8::1"}.<br/>
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     {@code 20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 01}
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>An IPv6 "IPv4 compatible" (or "compat") address,
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     {@code "::192.168.0.1"}.<br/>
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     {@code 00 00 00 00 00 00 00 00 00 00 00 00 c0 a8 00 01}
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>An IPv6 "IPv4 mapped" address, {@code "::ffff:192.168.0.1"}.<br/>
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     {@code 00 00 00 00 00 00 00 00 00 00 ff ff c0 a8 00 01}
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ul>
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>A few notes about IPv6 "IPv4 mapped" addresses and their observed
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * use in Java.
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <br><br>
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * "IPv4 mapped" addresses were originally a representation of IPv4
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * addresses for use on an IPv6 socket that could receive both IPv4
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * and IPv6 connections (by disabling the {@code IPV6_V6ONLY} socket
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * option on an IPv6 socket).  Yes, it's confusing.  Nevertheless,
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * these "mapped" addresses were never supposed to be seen on the
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * wire.  That assumption was dropped, some say mistakenly, in later
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * RFCs with the apparent aim of making IPv4-to-IPv6 transition simpler.
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Technically one <i>can</i> create a 128bit IPv6 address with the wire
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * format of a "mapped" address, as shown above, and transmit it in an
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * IPv6 packet header.  However, Java's InetAddress creation methods
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * appear to adhere doggedly to the original intent of the "mapped"
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * address: all "mapped" addresses return {@link Inet4Address} objects.
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>For added safety, it is common for IPv6 network operators to filter
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * all packets where either the source or destination address appears to
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * be a "compat" or "mapped" address.  Filtering suggestions usually
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * recommend discarding any packets with source or destination addresses
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in the invalid range {@code ::/3}, which includes both of these bizarre
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * address formats.  For more information on "bogons", including lists
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * of IPv6 bogon space, see:
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <ul>
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li><a target="_parent"
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *        href="http://en.wikipedia.org/wiki/Bogon_filtering"
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       >http://en.wikipedia.org/wiki/Bogon_filtering</a>
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li><a target="_parent"
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *        href="http://www.cymru.com/Bogons/ipv6.txt"
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       >http://www.cymru.com/Bogons/ipv6.txt</a>
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li><a target="_parent"
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *        href="http://www.cymru.com/Bogons/v6bogon.html"
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       >http://www.cymru.com/Bogons/v6bogon.html</a>
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li><a target="_parent"
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *        href="http://www.space.net/~gert/RIPE/ipv6-filters.html"
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       >http://www.space.net/~gert/RIPE/ipv6-filters.html</a>
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ul>
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Erik Kline
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 5.0
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class InetAddresses {
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final int IPV4_PART_COUNT = 4;
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final int IPV6_PART_COUNT = 8;
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final Inet4Address LOOPBACK4 =
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      (Inet4Address) forString("127.0.0.1");
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final Inet4Address ANY4 =
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      (Inet4Address) forString("0.0.0.0");
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private InetAddresses() {}
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an {@link Inet4Address}, given a byte array representation
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of the IPv4 address.
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param bytes byte array representing an IPv4 address (should be
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *              of length 4).
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@link Inet4Address} corresponding to the supplied byte
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         array.
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if a valid {@link Inet4Address}
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         can not be created.
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static Inet4Address getInet4Address(byte[] bytes) {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkArgument(bytes.length == 4,
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "Byte array has invalid length for an IPv4 address: %s != 4.",
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        bytes.length);
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      InetAddress ipv4 = InetAddress.getByAddress(bytes);
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!(ipv4 instanceof Inet4Address)) {
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new UnknownHostException(
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            String.format("'%s' is not an IPv4 address.",
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                          ipv4.getHostAddress()));
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (Inet4Address) ipv4;
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (UnknownHostException e) {
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      /*
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * This really shouldn't happen in practice since all our byte
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * sequences should be valid IP addresses.
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       *
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * However {@link InetAddress#getByAddress} is documented as
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * potentially throwing this "if IP address is of illegal length".
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       *
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * This is mapped to IllegalArgumentException since, presumably,
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * the argument triggered some bizarre processing bug.
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       */
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalArgumentException(
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          String.format("Host address '%s' is not a valid IPv4 address.",
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                        Arrays.toString(bytes)),
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          e);
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the {@link InetAddress} having the given string
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * representation.
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This deliberately avoids all nameservice lookups (e.g. no DNS).
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ipString {@code String} containing an IPv4 or IPv6 string literal,
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *                 e.g. {@code "192.168.0.1"} or {@code "2001:db8::1"}
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@link InetAddress} representing the argument
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if the argument is not a valid
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         IP string literal
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static InetAddress forString(String ipString) {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] addr = ipStringToBytes(ipString);
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The argument was malformed, i.e. not an IP string literal.
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (addr == null) {
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalArgumentException(
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          String.format("'%s' is not an IP string literal.", ipString));
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return InetAddress.getByAddress(addr);
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (UnknownHostException e) {
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      /*
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * This really shouldn't happen in practice since all our byte
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * sequences should be valid IP addresses.
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       *
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * However {@link InetAddress#getByAddress} is documented as
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * potentially throwing this "if IP address is of illegal length".
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       *
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * This is mapped to IllegalArgumentException since, presumably,
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * the argument triggered some processing bug in either
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * {@link IPAddressUtil#textToNumericFormatV4} or
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * {@link IPAddressUtil#textToNumericFormatV6}.
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       */
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalArgumentException(
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          String.format("'%s' is extremely broken.", ipString), e);
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns {@code true} if the supplied string is a valid IP string
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * literal, {@code false} otherwise.
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ipString {@code String} to evaluated as an IP string literal
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code true} if the argument is a valid IP string literal
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean isInetAddress(String ipString) {
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return ipStringToBytes(ipString) != null;
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static byte[] ipStringToBytes(String ipString) {
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Make a first pass to categorize the characters in this string.
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean hasColon = false;
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean hasDot = false;
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < ipString.length(); i++) {
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      char c = ipString.charAt(i);
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (c == '.') {
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        hasDot = true;
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else if (c == ':') {
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (hasDot) {
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return null;  // Colons must not appear after dots.
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        hasColon = true;
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else if (Character.digit(c, 16) == -1) {
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;  // Everything else must be a decimal or hex digit.
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Now decide which address family to parse.
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hasColon) {
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (hasDot) {
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ipString = convertDottedQuadToHex(ipString);
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (ipString == null) {
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return null;
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return textToNumericFormatV6(ipString);
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else if (hasDot) {
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return textToNumericFormatV4(ipString);
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return null;
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static byte[] textToNumericFormatV4(String ipString) {
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    String[] address = ipString.split("\\.", IPV4_PART_COUNT + 1);
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (address.length != IPV4_PART_COUNT) {
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = new byte[IPV4_PART_COUNT];
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < bytes.length; i++) {
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        bytes[i] = parseOctet(address[i]);
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NumberFormatException ex) {
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return bytes;
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static byte[] textToNumericFormatV6(String ipString) {
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // An address can have [2..8] colons, and N colons make N+1 parts.
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    String[] parts = ipString.split(":", IPV6_PART_COUNT + 2);
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (parts.length < 3 || parts.length > IPV6_PART_COUNT + 1) {
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Disregarding the endpoints, find "::" with nothing in between.
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // This indicates that a run of zeroes has been skipped.
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int skipIndex = -1;
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 1; i < parts.length - 1; i++) {
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (parts[i].length() == 0) {
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (skipIndex >= 0) {
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return null;  // Can't have more than one ::
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        skipIndex = i;
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int partsHi;  // Number of parts to copy from above/before the "::"
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int partsLo;  // Number of parts to copy from below/after the "::"
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (skipIndex >= 0) {
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // If we found a "::", then check if it also covers the endpoints.
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      partsHi = skipIndex;
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      partsLo = parts.length - skipIndex - 1;
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (parts[0].length() == 0 && --partsHi != 0) {
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;  // ^: requires ^::
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (parts[parts.length - 1].length() == 0 && --partsLo != 0) {
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;  // :$ requires ::$
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Otherwise, allocate the entire address to partsHi.  The endpoints
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // could still be empty, but parseHextet() will check for that.
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      partsHi = parts.length;
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      partsLo = 0;
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // If we found a ::, then we must have skipped at least one part.
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Otherwise, we must have exactly the right number of parts.
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int partsSkipped = IPV6_PART_COUNT - (partsHi + partsLo);
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!(skipIndex >= 0 ? partsSkipped >= 1 : partsSkipped == 0)) {
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Now parse the hextets into a byte array.
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ByteBuffer rawBytes = ByteBuffer.allocate(2 * IPV6_PART_COUNT);
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < partsHi; i++) {
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        rawBytes.putShort(parseHextet(parts[i]));
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < partsSkipped; i++) {
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        rawBytes.putShort((short) 0);
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = partsLo; i > 0; i--) {
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        rawBytes.putShort(parseHextet(parts[parts.length - i]));
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NumberFormatException ex) {
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return rawBytes.array();
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static String convertDottedQuadToHex(String ipString) {
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int lastColon = ipString.lastIndexOf(':');
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    String initialPart = ipString.substring(0, lastColon + 1);
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    String dottedQuad = ipString.substring(lastColon + 1);
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] quad = textToNumericFormatV4(dottedQuad);
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (quad == null) {
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    String penultimate = Integer.toHexString(((quad[0] & 0xff) << 8) | (quad[1] & 0xff));
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    String ultimate = Integer.toHexString(((quad[2] & 0xff) << 8) | (quad[3] & 0xff));
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return initialPart + penultimate + ":" + ultimate;
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static byte parseOctet(String ipPart) {
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Note: we already verified that this string contains only hex digits.
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int octet = Integer.parseInt(ipPart);
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Disallow leading zeroes, because no clear standard exists on
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // whether these should be interpreted as decimal or octal.
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (octet > 255 || (ipPart.startsWith("0") && ipPart.length() > 1)) {
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new NumberFormatException();
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (byte) octet;
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static short parseHextet(String ipPart) {
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Note: we already verified that this string contains only hex digits.
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hextet = Integer.parseInt(ipPart, 16);
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hextet > 0xffff) {
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new NumberFormatException();
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (short) hextet;
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the string representation of an {@link InetAddress}.
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>For IPv4 addresses, this is identical to
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link InetAddress#getHostAddress()}, but for IPv6 addresses, the output
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * follows <a href="http://tools.ietf.org/html/rfc5952">RFC 5952</a>
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * section 4.  The main difference is that this method uses "::" for zero
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * compression, while Java's version uses the uncompressed form.
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This method uses hexadecimal for all IPv6 addresses, including
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * IPv4-mapped IPv6 addresses such as "::c000:201".  The output does not
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * include a Scope ID.
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link InetAddress} to be converted to an address string
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code String} containing the text-formatted IP address
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 10.0
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static String toAddrString(InetAddress ip) {
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkNotNull(ip);
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (ip instanceof Inet4Address) {
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // For IPv4, Java's formatting is good enough.
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return ip.getHostAddress();
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkArgument(ip instanceof Inet6Address);
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = ip.getAddress();
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int[] hextets = new int[IPV6_PART_COUNT];
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < hextets.length; i++) {
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      hextets[i] = Ints.fromBytes(
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          (byte) 0, (byte) 0, bytes[2 * i], bytes[2 * i + 1]);
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    compressLongestRunOfZeroes(hextets);
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return hextetsToIPv6String(hextets);
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Identify and mark the longest run of zeroes in an IPv6 address.
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Only runs of two or more hextets are considered.  In case of a tie, the
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * leftmost run wins.  If a qualifying run is found, its hextets are replaced
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * by the sentinel value -1.
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param hextets {@code int[]} mutable array of eight 16-bit hextets.
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static void compressLongestRunOfZeroes(int[] hextets) {
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int bestRunStart = -1;
4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int bestRunLength = -1;
4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int runStart = -1;
4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < hextets.length + 1; i++) {
4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (i < hextets.length && hextets[i] == 0) {
4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (runStart < 0) {
4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          runStart = i;
4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else if (runStart >= 0) {
4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int runLength = i - runStart;
4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (runLength > bestRunLength) {
4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          bestRunStart = runStart;
4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          bestRunLength = runLength;
4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        runStart = -1;
4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (bestRunLength >= 2) {
4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Arrays.fill(hextets, bestRunStart, bestRunStart + bestRunLength, -1);
4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Convert a list of hextets into a human-readable IPv6 address.
4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>In order for "::" compression to work, the input should contain negative
4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * sentinel values in place of the elided zeroes.
4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param hextets {@code int[]} array of eight 16-bit hextets, or -1s.
4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static String hextetsToIPv6String(int[] hextets) {
4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * While scanning the array, handle these state transitions:
4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *   start->num => "num"     start->gap => "::"
4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *   num->num   => ":num"    num->gap   => "::"
4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *   gap->num   => "num"     gap->gap   => ""
4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    StringBuilder buf = new StringBuilder(39);
4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean lastWasNumber = false;
4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < hextets.length; i++) {
4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean thisIsNumber = hextets[i] >= 0;
4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (thisIsNumber) {
4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (lastWasNumber) {
4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          buf.append(':');
4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        buf.append(Integer.toHexString(hextets[i]));
4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (i == 0 || lastWasNumber) {
4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          buf.append("::");
4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lastWasNumber = thisIsNumber;
4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return buf.toString();
4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the string representation of an {@link InetAddress} suitable
4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * for inclusion in a URI.
4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>For IPv4 addresses, this is identical to
4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link InetAddress#getHostAddress()}, but for IPv6 addresses it
4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * compresses zeroes and surrounds the text with square brackets; for example
4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code "[2001:db8::1]"}.
4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Per section 3.2.2 of
4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <a target="_parent"
4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    href="http://tools.ietf.org/html/rfc3986#section-3.2.2"
4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *  >http://tools.ietf.org/html/rfc3986</a>,
4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * a URI containing an IPv6 string literal is of the form
4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code "http://[2001:db8::1]:8888/index.html"}.
4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Use of either {@link InetAddresses#toAddrString},
4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link InetAddress#getHostAddress()}, or this method is recommended over
4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link InetAddress#toString()} when an IP address string literal is
4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * desired.  This is because {@link InetAddress#toString()} prints the
4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * hostname and the IP address string joined by a "/".
4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link InetAddress} to be converted to URI string literal
4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code String} containing URI-safe string literal
4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static String toUriString(InetAddress ip) {
4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (ip instanceof Inet6Address) {
5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return "[" + toAddrString(ip) + "]";
5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return toAddrString(ip);
5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an InetAddress representing the literal IPv4 or IPv6 host
5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * portion of a URL, encoded in the format specified by RFC 3986 section 3.2.2.
5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This function is similar to {@link InetAddresses#forString(String)},
5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * however, it requires that IPv6 addresses are surrounded by square brackets.
5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This function is the inverse of
5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link InetAddresses#toUriString(java.net.InetAddress)}.
5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param hostAddr A RFC 3986 section 3.2.2 encoded IPv4 or IPv6 address
5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return an InetAddress representing the address in {@code hostAddr}
5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if {@code hostAddr} is not a valid
5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     IPv4 address, or IPv6 address surrounded by square brackets
5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static InetAddress forUriString(String hostAddr) {
5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkNotNull(hostAddr);
5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkArgument(hostAddr.length() > 0, "host string is empty");
5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    InetAddress retval = null;
5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // IPv4 address?
5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      retval = forString(hostAddr);
5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (retval instanceof Inet4Address) {
5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return retval;
5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException e) {
5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Not a valid IP address, fall through.
5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // IPv6 address
5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!(hostAddr.startsWith("[") && hostAddr.endsWith("]"))) {
5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalArgumentException("Not a valid address: \"" + hostAddr + '"');
5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    retval = forString(hostAddr.substring(1, hostAddr.length() - 1));
5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (retval instanceof Inet6Address) {
5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return retval;
5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    throw new IllegalArgumentException("Not a valid address: \"" + hostAddr + '"');
5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns {@code true} if the supplied string is a valid URI IP string
5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * literal, {@code false} otherwise.
5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ipString {@code String} to evaluated as an IP URI host string literal
5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code true} if the argument is a valid IP URI host
5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean isUriInetAddress(String ipString) {
5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      forUriString(ipString);
5581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException e) {
5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
5651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Evaluates whether the argument is an IPv6 "compat" address.
5661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>An "IPv4 compatible", or "compat", address is one with 96 leading
5681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * bits of zero, with the remaining 32 bits interpreted as an
5691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * IPv4 address.  These are conventionally represented in string
5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * literals as {@code "::192.168.0.1"}, though {@code "::c0a8:1"} is
5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * also considered an IPv4 compatible address (and equivalent to
5721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code "::192.168.0.1"}).
5731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>For more on IPv4 compatible addresses see section 2.5.5.1 of
5751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <a target="_parent"
5761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    href="http://tools.ietf.org/html/rfc4291#section-2.5.5.1"
5771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    >http://tools.ietf.org/html/rfc4291</a>
5781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>NOTE: This method is different from
5801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link Inet6Address#isIPv4CompatibleAddress} in that it more
5811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * correctly classifies {@code "::"} and {@code "::1"} as
5821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * proper IPv6 addresses (which they are), NOT IPv4 compatible
5831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * addresses (which they are generally NOT considered to be).
5841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for embedded IPv4
5861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *           compatible address format
5871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code true} if the argument is a valid "compat" address
5881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
5891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean isCompatIPv4Address(Inet6Address ip) {
5901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!ip.isIPv4CompatibleAddress()) {
5911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
5921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = ip.getAddress();
5951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if ((bytes[12] == 0) && (bytes[13] == 0) && (bytes[14] == 0)
5961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            && ((bytes[15] == 0) || (bytes[15] == 1))) {
5971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
5981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return true;
6011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the IPv4 address embedded in an IPv4 compatible address.
6051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for an embedded
6071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *           IPv4 address
6081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@link Inet4Address} of the embedded IPv4 address
6091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if the argument is not a valid
6101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         IPv4 compatible address
6111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static Inet4Address getCompatIPv4Address(Inet6Address ip) {
6131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkArgument(isCompatIPv4Address(ip),
6141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "Address '%s' is not IPv4-compatible.", toAddrString(ip));
6151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return getInet4Address(copyOfRange(ip.getAddress(), 12, 16));
6171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Evaluates whether the argument is a 6to4 address.
6211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>6to4 addresses begin with the {@code "2002::/16"} prefix.
6231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The next 32 bits are the IPv4 address of the host to which
6241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * IPv6-in-IPv4 tunneled packets should be routed.
6251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>For more on 6to4 addresses see section 2 of
6271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <a target="_parent" href="http://tools.ietf.org/html/rfc3056#section-2"
6281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    >http://tools.ietf.org/html/rfc3056</a>
6291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for 6to4 address
6311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *        format
6321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code true} if the argument is a 6to4 address
6331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean is6to4Address(Inet6Address ip) {
6351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = ip.getAddress();
6361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (bytes[0] == (byte) 0x20) && (bytes[1] == (byte) 0x02);
6371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the IPv4 address embedded in a 6to4 address.
6411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for embedded IPv4
6431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *           in 6to4 address.
6441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@link Inet4Address} of embedded IPv4 in 6to4 address.
6451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if the argument is not a valid
6461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         IPv6 6to4 address.
6471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static Inet4Address get6to4IPv4Address(Inet6Address ip) {
6491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkArgument(is6to4Address(ip),
6501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "Address '%s' is not a 6to4 address.", toAddrString(ip));
6511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return getInet4Address(copyOfRange(ip.getAddress(), 2, 6));
6531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A simple data class to encapsulate the information to be found in a
6571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Teredo address.
6581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>All of the fields in this class are encoded in various portions
6601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of the IPv6 address as part of the protocol.  More protocols details
6611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * can be found at:
6621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <a target="_parent" href="http://en.wikipedia.org/wiki/Teredo_tunneling"
6631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    >http://en.wikipedia.org/wiki/Teredo_tunneling</a>.
6641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The RFC can be found here:
6661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <a target="_parent" href="http://tools.ietf.org/html/rfc4380"
6671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    >http://tools.ietf.org/html/rfc4380</a>.
6681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 5.0
6701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Beta
6721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static final class TeredoInfo {
6731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final Inet4Address server;
6741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final Inet4Address client;
6751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final int port;
6761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final int flags;
6771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Constructs a TeredoInfo instance.
6801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
6811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * <p>Both server and client can be {@code null}, in which case the
6821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * value {@code "0.0.0.0"} will be assumed.
6831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
6841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @throws IllegalArgumentException if either of the {@code port}
6851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *         or the {@code flags} arguments are out of range of an
6861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *         unsigned short
6871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO: why is this public?
6891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public TeredoInfo(@Nullable Inet4Address server,
6901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      @Nullable Inet4Address client,
6911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      int port, int flags) {
6921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Preconditions.checkArgument((port >= 0) && (port <= 0xffff),
6931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          "port '%s' is out of range (0 <= port <= 0xffff)", port);
6941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Preconditions.checkArgument((flags >= 0) && (flags <= 0xffff),
6951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          "flags '%s' is out of range (0 <= flags <= 0xffff)", flags);
6961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (server != null) {
6981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.server = server;
6991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
7001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.server = ANY4;
7011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
7021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (client != null) {
7041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.client = client;
7051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
7061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.client = ANY4;
7071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
7081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.port = port;
7101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.flags = flags;
7111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Inet4Address getServer() {
7141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return server;
7151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Inet4Address getClient() {
7181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return client;
7191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getPort() {
7221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return port;
7231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getFlags() {
7261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return flags;
7271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Evaluates whether the argument is a Teredo address.
7321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Teredo addresses begin with the {@code "2001::/32"} prefix.
7341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for Teredo address
7361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *        format.
7371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code true} if the argument is a Teredo address
7381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean isTeredoAddress(Inet6Address ip) {
7401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = ip.getAddress();
7411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (bytes[0] == (byte) 0x20) && (bytes[1] == (byte) 0x01)
7421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert           && (bytes[2] == 0) && (bytes[3] == 0);
7431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the Teredo information embedded in a Teredo address.
7471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for embedded Teredo
7491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *           information
7501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return extracted {@code TeredoInfo}
7511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if the argument is not a valid
7521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         IPv6 Teredo address
7531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static TeredoInfo getTeredoInfo(Inet6Address ip) {
7551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkArgument(isTeredoAddress(ip),
7561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "Address '%s' is not a Teredo address.", toAddrString(ip));
7571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = ip.getAddress();
7591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Inet4Address server = getInet4Address(copyOfRange(bytes, 4, 8));
7601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int flags = ByteStreams.newDataInput(bytes, 8).readShort() & 0xffff;
7621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Teredo obfuscates the mapped client port, per section 4 of the RFC.
7641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int port = ~ByteStreams.newDataInput(bytes, 10).readShort() & 0xffff;
7651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] clientBytes = copyOfRange(bytes, 12, 16);
7671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < clientBytes.length; i++) {
7681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Teredo obfuscates the mapped client IP, per section 4 of the RFC.
7691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      clientBytes[i] = (byte) ~clientBytes[i];
7701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Inet4Address client = getInet4Address(clientBytes);
7721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new TeredoInfo(server, client, port, flags);
7741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Evaluates whether the argument is an ISATAP address.
7781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>From RFC 5214: "ISATAP interface identifiers are constructed in
7801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Modified EUI-64 format [...] by concatenating the 24-bit IANA OUI
7811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * (00-00-5E), the 8-bit hexadecimal value 0xFE, and a 32-bit IPv4
7821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * address in network byte order [...]"
7831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>For more on ISATAP addresses see section 6.1 of
7851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <a target="_parent" href="http://tools.ietf.org/html/rfc5214#section-6.1"
7861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    >http://tools.ietf.org/html/rfc5214</a>
7871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for ISATAP address
7891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *        format.
7901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code true} if the argument is an ISATAP address
7911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean isIsatapAddress(Inet6Address ip) {
7931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // If it's a Teredo address with the right port (41217, or 0xa101)
7951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // which would be encoded as 0x5efe then it can't be an ISATAP address.
7961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (isTeredoAddress(ip)) {
7971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
7981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = ip.getAddress();
8011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if ((bytes[8] | (byte) 0x03) != (byte) 0x03) {
8031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Verify that high byte of the 64 bit identifier is zero, modulo
8051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // the U/L and G bits, with which we are not concerned.
8061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
8071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (bytes[9] == (byte) 0x00) && (bytes[10] == (byte) 0x5e)
8101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert           && (bytes[11] == (byte) 0xfe);
8111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
8141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the IPv4 address embedded in an ISATAP address.
8151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for embedded IPv4
8171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *           in ISATAP address
8181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@link Inet4Address} of embedded IPv4 in an ISATAP address
8191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if the argument is not a valid
8201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         IPv6 ISATAP address
8211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
8221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static Inet4Address getIsatapIPv4Address(Inet6Address ip) {
8231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkArgument(isIsatapAddress(ip),
8241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "Address '%s' is not an ISATAP address.", toAddrString(ip));
8251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return getInet4Address(copyOfRange(ip.getAddress(), 12, 16));
8271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
8301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Examines the Inet6Address to determine if it is an IPv6 address of one
8311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of the specified address types that contain an embedded IPv4 address.
8321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>NOTE: ISATAP addresses are explicitly excluded from this method
8341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * due to their trivial spoofability.  With other transition addresses
8351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * spoofing involves (at least) infection of one's BGP routing table.
8361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for embedded IPv4
8381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *           client address.
8391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code true} if there is an embedded IPv4 client address.
8401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 7.0
8411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
8421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean hasEmbeddedIPv4ClientAddress(Inet6Address ip) {
8431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return isCompatIPv4Address(ip) || is6to4Address(ip) ||
8441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert           isTeredoAddress(ip);
8451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
8481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Examines the Inet6Address to extract the embedded IPv4 client address
8491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * if the InetAddress is an IPv6 address of one of the specified address
8501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * types that contain an embedded IPv4 address.
8511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>NOTE: ISATAP addresses are explicitly excluded from this method
8531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * due to their trivial spoofability.  With other transition addresses
8541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * spoofing involves (at least) infection of one's BGP routing table.
8551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link Inet6Address} to be examined for embedded IPv4
8571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *           client address.
8581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@link Inet4Address} of embedded IPv4 client address.
8591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if the argument does not have a valid
8601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         embedded IPv4 address.
8611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
8621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static Inet4Address getEmbeddedIPv4ClientAddress(Inet6Address ip) {
8631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (isCompatIPv4Address(ip)) {
8641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return getCompatIPv4Address(ip);
8651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (is6to4Address(ip)) {
8681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return get6to4IPv4Address(ip);
8691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (isTeredoAddress(ip)) {
8721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return getTeredoInfo(ip).getClient();
8731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    throw new IllegalArgumentException(
8761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        String.format("'%s' has no embedded IPv4 address.",
8771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      toAddrString(ip)));
8781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
8811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Evaluates whether the argument is an "IPv4 mapped" IPv6 address.
8821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>An "IPv4 mapped" address is anything in the range ::ffff:0:0/96
8841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * (sometimes written as ::ffff:0.0.0.0/96), with the last 32 bits
8851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * interpreted as an IPv4 address.
8861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>For more on IPv4 mapped addresses see section 2.5.5.2 of
8881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <a target="_parent"
8891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    href="http://tools.ietf.org/html/rfc4291#section-2.5.5.2"
8901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *    >http://tools.ietf.org/html/rfc4291</a>
8911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Note: This method takes a {@code String} argument because
8931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link InetAddress} automatically collapses mapped addresses to IPv4.
8941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * (It is actually possible to avoid this using one of the obscure
8951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link Inet6Address} methods, but it would be unwise to depend on such
8961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * a poorly-documented feature.)
8971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
8981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ipString {@code String} to be examined for embedded IPv4-mapped
8991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     IPv6 address format
9001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code true} if the argument is a valid "mapped" address
9011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 10.0
9021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
9031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean isMappedIPv4Address(String ipString) {
9041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = ipStringToBytes(ipString);
9051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (bytes != null && bytes.length == 16) {
9061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < 10; i++) {
9071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (bytes[i] != 0) {
9081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return false;
9091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
9101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
9111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 10; i < 12; i++) {
9121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (bytes[i] != (byte) 0xff) {
9131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return false;
9141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
9151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
9161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
9171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
9191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
9201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
9221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Coerces an IPv6 address into an IPv4 address.
9231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
9241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>HACK: As long as applications continue to use IPv4 addresses for
9251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * indexing into tables, accounting, et cetera, it may be necessary to
9261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <b>coerce</b> IPv6 addresses into IPv4 addresses. This function does
9271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * so by hashing the upper 64 bits into {@code 224.0.0.0/3}
9281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * (64 bits into 29 bits).
9291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
9301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>A "coerced" IPv4 address is equivalent to itself.
9311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
9321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>NOTE: This function is failsafe for security purposes: ALL IPv6
9331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * addresses (except localhost (::1)) are hashed to avoid the security
9341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * risk associated with extracting an embedded IPv4 address that might
9351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * permit elevated privileges.
9361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
9371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link InetAddress} to "coerce"
9381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@link Inet4Address} represented "coerced" address
9391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 7.0
9401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
9411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static Inet4Address getCoercedIPv4Address(InetAddress ip) {
9421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (ip instanceof Inet4Address) {
9431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (Inet4Address) ip;
9441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Special cases:
9471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] bytes = ip.getAddress();
9481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean leadingBytesOfZero = true;
9491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < 15; ++i) {
9501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (bytes[i] != 0) {
9511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        leadingBytesOfZero = false;
9521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        break;
9531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
9541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (leadingBytesOfZero && (bytes[15] == 1)) {
9561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LOOPBACK4;  // ::1
9571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else if (leadingBytesOfZero && (bytes[15] == 0)) {
9581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return ANY4;  // ::0
9591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Inet6Address ip6 = (Inet6Address) ip;
9621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long addressAsLong = 0;
9631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hasEmbeddedIPv4ClientAddress(ip6)) {
9641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      addressAsLong = getEmbeddedIPv4ClientAddress(ip6).hashCode();
9651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
9661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Just extract the high 64 bits (assuming the rest is user-modifiable).
9681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      addressAsLong = ByteBuffer.wrap(ip6.getAddress(), 0, 8).getLong();
9691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Many strategies for hashing are possible.  This might suffice for now.
9721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int coercedHash = hash64To32(addressAsLong);
9731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Squash into 224/4 Multicast and 240/4 Reserved space (i.e. 224/3).
9751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    coercedHash |= 0xe0000000;
9761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Fixup to avoid some "illegal" values.  Currently the only potential
9781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // illegal value is 255.255.255.255.
9791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (coercedHash == 0xffffffff) {
9801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      coercedHash = 0xfffffffe;
9811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return getInet4Address(Ints.toByteArray(coercedHash));
9841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
9851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
9871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an {@code int} hash of a 64-bit long.
9881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
9891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This comes from http://www.concentric.net/~ttwang/tech/inthash.htm
9901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
9911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This hash gives no guarantees on the cryptographic suitability nor the
9921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * quality of randomness produced, and the mapping may change in the future.
9931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
9941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param key A 64-bit number to hash
9951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code int} the input hashed into 32 bits
9961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
9971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @VisibleForTesting static int hash64To32(long key) {
9981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    key = (~key) + (key << 18);
9991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    key = key ^ (key >>> 31);
10001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    key = key * 21;
10011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    key = key ^ (key >>> 11);
10021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    key = key + (key << 6);
10031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    key = key ^ (key >>> 22);
10041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (int) key;
10051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
10061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
10081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an integer representing an IPv4 address regardless of
10091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * whether the supplied argument is an IPv4 address or not.
10101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>IPv6 addresses are <b>coerced</b> to IPv4 addresses before being
10121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * converted to integers.
10131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>As long as there are applications that assume that all IP addresses
10151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * are IPv4 addresses and can therefore be converted safely to integers
10161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * (for whatever purpose) this function can be used to handle IPv6
10171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * addresses as well until the application is suitably fixed.
10181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>NOTE: an IPv6 address coerced to an IPv4 address can only be used
10201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * for such purposes as rudimentary identification or indexing into a
10211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * collection of real {@link InetAddress}es.  They cannot be used as
10221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * real addresses for the purposes of network communication.
10231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param ip {@link InetAddress} to convert
10251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code int}, "coerced" if ip is not an IPv4 address
10261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 7.0
10271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
10281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static int coerceToInteger(InetAddress ip) {
10291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return ByteStreams.newDataInput(getCoercedIPv4Address(ip).getAddress()).readInt();
10301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
10311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
10331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an Inet4Address having the integer value specified by
10341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the argument.
10351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param address {@code int}, the 32bit integer address to be converted
10371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@link Inet4Address} equivalent of the argument
10381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
10391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static Inet4Address fromInteger(int address) {
10401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return getInet4Address(Ints.toByteArray(address));
10411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
10421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
10441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an address from a <b>little-endian ordered</b> byte array
10451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * (the opposite of what {@link InetAddress#getByAddress} expects).
10461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>IPv4 address byte array must be 4 bytes long and IPv6 byte array
10481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * must be 16 bytes long.
10491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param addr the raw IP address in little-endian byte order
10511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return an InetAddress object created from the raw IP address
10521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws UnknownHostException if IP address is of illegal length
10531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
10541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static InetAddress fromLittleEndianByteArray(byte[] addr)
10551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws UnknownHostException {
10561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] reversed = new byte[addr.length];
10571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < addr.length; i++) {
10581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      reversed[i] = addr[addr.length - i - 1];
10591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return InetAddress.getByAddress(reversed);
10611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
10621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
10641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a new InetAddress that is one more than the passed in address.
10651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This method works for both IPv4 and IPv6 addresses.
10661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param address the InetAddress to increment
10681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a new InetAddress that is one more than the passed in address.
10691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if InetAddress is at the end of its
10701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *         range.
10711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 10.0
10721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
10731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static InetAddress increment(InetAddress address) {
10741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] addr = address.getAddress();
10751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int i = addr.length - 1;
10761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    while (i >= 0 && addr[i] == (byte) 0xff) {
10771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      addr[i] = 0;
10781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      i--;
10791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkArgument(i >= 0, "Incrementing %s would wrap.", address);
10821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    addr[i]++;
10841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
10851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return InetAddress.getByAddress(addr);
10861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (UnknownHostException e) {
10871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError(e);
10881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
10901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
10921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns true if the InetAddress is either 255.255.255.255 for IPv4 or
10931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff for IPv6.
10941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
10951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return true if the InetAddress is either 255.255.255.255 for IPv4 or
10961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *          ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff for IPv6.
10971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 10.0
10981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
10991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static boolean isMaximum(InetAddress address) {
11001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] addr = address.getAddress();
11011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < addr.length; i++) {
11021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (addr[i] != (byte) 0xff) {
11031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
11041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
11051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return true;
11071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
11081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
11101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This method emulates the Java 6 method
11111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code Arrays.copyOfRange(byte, int, int)}, which is not available in
11121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Java 5, and thus cannot be used in Guava code.
11131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
11141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static byte[] copyOfRange(byte[] original, int from, int to) {
11151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Preconditions.checkNotNull(original);
11161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int end = Math.min(to, original.length);
11181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    byte[] result = new byte[to - from];
11191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    System.arraycopy(original, from, result, 0, end - from);
11211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return result;
11221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
11231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
1124