Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net;
     18 
     19 import java.net.Inet4Address;
     20 import java.net.Inet6Address;
     21 import java.net.InetAddress;
     22 import java.net.InterfaceAddress;
     23 import java.net.NetworkInterface;
     24 import java.net.SocketException;
     25 import java.util.Arrays;
     26 import java.util.Collections;
     27 import java.util.Comparator;
     28 import java.util.List;
     29 
     30 import android.net.LinkAddress;
     31 import android.os.Parcel;
     32 import android.test.AndroidTestCase;
     33 import static android.test.MoreAsserts.assertNotEqual;
     34 import android.test.suitebuilder.annotation.SmallTest;
     35 
     36 import static android.system.OsConstants.IFA_F_DEPRECATED;
     37 import static android.system.OsConstants.IFA_F_PERMANENT;
     38 import static android.system.OsConstants.IFA_F_TENTATIVE;
     39 import static android.system.OsConstants.RT_SCOPE_HOST;
     40 import static android.system.OsConstants.RT_SCOPE_LINK;
     41 import static android.system.OsConstants.RT_SCOPE_SITE;
     42 import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
     43 
     44 /**
     45  * Tests for {@link LinkAddress}.
     46  */
     47 public class LinkAddressTest extends AndroidTestCase {
     48 
     49     private static final String V4 = "192.0.2.1";
     50     private static final String V6 = "2001:db8::1";
     51     private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
     52     private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);
     53 
     54     public void testConstants() {
     55         // RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero.
     56         assertNotEqual(0, RT_SCOPE_HOST);
     57         assertNotEqual(0, RT_SCOPE_LINK);
     58         assertNotEqual(0, RT_SCOPE_SITE);
     59 
     60         assertNotEqual(0, IFA_F_DEPRECATED);
     61         assertNotEqual(0, IFA_F_PERMANENT);
     62         assertNotEqual(0, IFA_F_TENTATIVE);
     63     }
     64 
     65     public void testConstructors() throws SocketException {
     66         LinkAddress address;
     67 
     68         // Valid addresses work as expected.
     69         address = new LinkAddress(V4_ADDRESS, 25);
     70         assertEquals(V4_ADDRESS, address.getAddress());
     71         assertEquals(25, address.getPrefixLength());
     72         assertEquals(0, address.getFlags());
     73         assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
     74 
     75         address = new LinkAddress(V6_ADDRESS, 127);
     76         assertEquals(V6_ADDRESS, address.getAddress());
     77         assertEquals(127, address.getPrefixLength());
     78         assertEquals(0, address.getFlags());
     79         assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
     80 
     81         // Nonsensical flags/scopes or combinations thereof are acceptable.
     82         address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK);
     83         assertEquals(V6_ADDRESS, address.getAddress());
     84         assertEquals(64, address.getPrefixLength());
     85         assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags());
     86         assertEquals(RT_SCOPE_LINK, address.getScope());
     87 
     88         address = new LinkAddress(V4 + "/23", 123, 456);
     89         assertEquals(V4_ADDRESS, address.getAddress());
     90         assertEquals(23, address.getPrefixLength());
     91         assertEquals(123, address.getFlags());
     92         assertEquals(456, address.getScope());
     93 
     94         // InterfaceAddress doesn't have a constructor. Fetch some from an interface.
     95         List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses();
     96 
     97         // We expect to find 127.0.0.1/8 and ::1/128, in any order.
     98         LinkAddress ipv4Loopback, ipv6Loopback;
     99         assertEquals(2, addrs.size());
    100         if (addrs.get(0).getAddress() instanceof Inet4Address) {
    101             ipv4Loopback = new LinkAddress(addrs.get(0));
    102             ipv6Loopback = new LinkAddress(addrs.get(1));
    103         } else {
    104             ipv4Loopback = new LinkAddress(addrs.get(1));
    105             ipv6Loopback = new LinkAddress(addrs.get(0));
    106         }
    107 
    108         assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress());
    109         assertEquals(8, ipv4Loopback.getPrefixLength());
    110 
    111         assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress());
    112         assertEquals(128, ipv6Loopback.getPrefixLength());
    113 
    114         // Null addresses are rejected.
    115         try {
    116             address = new LinkAddress(null, 24);
    117             fail("Null InetAddress should cause IllegalArgumentException");
    118         } catch(IllegalArgumentException expected) {}
    119 
    120         try {
    121             address = new LinkAddress((String) null, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    122             fail("Null string should cause IllegalArgumentException");
    123         } catch(IllegalArgumentException expected) {}
    124 
    125         try {
    126             address = new LinkAddress((InterfaceAddress) null);
    127             fail("Null string should cause NullPointerException");
    128         } catch(NullPointerException expected) {}
    129 
    130         // Invalid prefix lengths are rejected.
    131         try {
    132             address = new LinkAddress(V4_ADDRESS, -1);
    133             fail("Negative IPv4 prefix length should cause IllegalArgumentException");
    134         } catch(IllegalArgumentException expected) {}
    135 
    136         try {
    137             address = new LinkAddress(V6_ADDRESS, -1);
    138             fail("Negative IPv6 prefix length should cause IllegalArgumentException");
    139         } catch(IllegalArgumentException expected) {}
    140 
    141         try {
    142             address = new LinkAddress(V4_ADDRESS, 33);
    143             fail("/33 IPv4 prefix length should cause IllegalArgumentException");
    144         } catch(IllegalArgumentException expected) {}
    145 
    146         try {
    147             address = new LinkAddress(V4 + "/33", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    148             fail("/33 IPv4 prefix length should cause IllegalArgumentException");
    149         } catch(IllegalArgumentException expected) {}
    150 
    151 
    152         try {
    153             address = new LinkAddress(V6_ADDRESS, 129, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    154             fail("/129 IPv6 prefix length should cause IllegalArgumentException");
    155         } catch(IllegalArgumentException expected) {}
    156 
    157         try {
    158             address = new LinkAddress(V6 + "/129", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    159             fail("/129 IPv6 prefix length should cause IllegalArgumentException");
    160         } catch(IllegalArgumentException expected) {}
    161 
    162         // Multicast addresses are rejected.
    163         try {
    164             address = new LinkAddress("224.0.0.2/32");
    165             fail("IPv4 multicast address should cause IllegalArgumentException");
    166         } catch(IllegalArgumentException expected) {}
    167 
    168         try {
    169             address = new LinkAddress("ff02::1/128");
    170             fail("IPv6 multicast address should cause IllegalArgumentException");
    171         } catch(IllegalArgumentException expected) {}
    172     }
    173 
    174     public void testAddressScopes() {
    175         assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope());
    176         assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope());
    177 
    178         assertEquals(RT_SCOPE_LINK, new LinkAddress("::1/128").getScope());
    179         assertEquals(RT_SCOPE_LINK, new LinkAddress("127.0.0.5/8").getScope());
    180         assertEquals(RT_SCOPE_LINK, new LinkAddress("fe80::ace:d00d/64").getScope());
    181         assertEquals(RT_SCOPE_LINK, new LinkAddress("169.254.5.12/16").getScope());
    182 
    183         assertEquals(RT_SCOPE_SITE, new LinkAddress("fec0::dead/64").getScope());
    184 
    185         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("10.1.2.3/21").getScope());
    186         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("192.0.2.1/25").getScope());
    187         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("2001:db8::/64").getScope());
    188         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("5000::/127").getScope());
    189     }
    190 
    191     private void assertIsSameAddressAs(LinkAddress l1, LinkAddress l2) {
    192         assertTrue(l1 + " unexpectedly does not have same address as " + l2,
    193                 l1.isSameAddressAs(l2));
    194         assertTrue(l2 + " unexpectedly does not have same address as " + l1,
    195                 l2.isSameAddressAs(l1));
    196     }
    197 
    198     private void assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2) {
    199         assertFalse(l1 + " unexpectedly has same address as " + l2,
    200                 l1.isSameAddressAs(l2));
    201         assertFalse(l2 + " unexpectedly has same address as " + l1,
    202                 l1.isSameAddressAs(l2));
    203     }
    204 
    205     private void assertLinkAddressesEqual(LinkAddress l1, LinkAddress l2) {
    206         assertTrue(l1 + " unexpectedly not equal to " + l2, l1.equals(l2));
    207         assertTrue(l2 + " unexpectedly not equal to " + l1, l2.equals(l1));
    208         assertEquals(l1.hashCode(), l2.hashCode());
    209     }
    210 
    211     private void assertLinkAddressesNotEqual(LinkAddress l1, LinkAddress l2) {
    212         assertFalse(l1 + " unexpectedly equal to " + l2, l1.equals(l2));
    213         assertFalse(l2 + " unexpectedly equal to " + l1, l2.equals(l1));
    214     }
    215 
    216     public void testEqualsAndSameAddressAs() {
    217         LinkAddress l1, l2, l3;
    218 
    219         l1 = new LinkAddress("2001:db8::1/64");
    220         l2 = new LinkAddress("2001:db8::1/64");
    221         assertLinkAddressesEqual(l1, l2);
    222         assertIsSameAddressAs(l1, l2);
    223 
    224         l2 = new LinkAddress("2001:db8::1/65");
    225         assertLinkAddressesNotEqual(l1, l2);
    226         assertIsNotSameAddressAs(l1, l2);
    227 
    228         l2 = new LinkAddress("2001:db8::2/64");
    229         assertLinkAddressesNotEqual(l1, l2);
    230         assertIsNotSameAddressAs(l1, l2);
    231 
    232 
    233         l1 = new LinkAddress("192.0.2.1/24");
    234         l2 = new LinkAddress("192.0.2.1/24");
    235         assertLinkAddressesEqual(l1, l2);
    236         assertIsSameAddressAs(l1, l2);
    237 
    238         l2 = new LinkAddress("192.0.2.1/23");
    239         assertLinkAddressesNotEqual(l1, l2);
    240         assertIsNotSameAddressAs(l1, l2);
    241 
    242         l2 = new LinkAddress("192.0.2.2/24");
    243         assertLinkAddressesNotEqual(l1, l2);
    244         assertIsNotSameAddressAs(l1, l2);
    245 
    246 
    247         // Check equals() and isSameAddressAs() on identical addresses with different flags.
    248         l1 = new LinkAddress(V6_ADDRESS, 64);
    249         l2 = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE);
    250         assertLinkAddressesEqual(l1, l2);
    251         assertIsSameAddressAs(l1, l2);
    252 
    253         l2 = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_UNIVERSE);
    254         assertLinkAddressesNotEqual(l1, l2);
    255         assertIsSameAddressAs(l1, l2);
    256 
    257         // Check equals() and isSameAddressAs() on identical addresses with different scope.
    258         l1 = new LinkAddress(V4_ADDRESS, 24);
    259         l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_UNIVERSE);
    260         assertLinkAddressesEqual(l1, l2);
    261         assertIsSameAddressAs(l1, l2);
    262 
    263         l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_HOST);
    264         assertLinkAddressesNotEqual(l1, l2);
    265         assertIsSameAddressAs(l1, l2);
    266 
    267         // Addresses with the same start or end bytes aren't equal between families.
    268         l1 = new LinkAddress("32.1.13.184/24");
    269         l2 = new LinkAddress("2001:db8::1/24");
    270         l3 = new LinkAddress("::2001:db8/24");
    271 
    272         byte[] ipv4Bytes = l1.getAddress().getAddress();
    273         byte[] l2FirstIPv6Bytes = Arrays.copyOf(l2.getAddress().getAddress(), 4);
    274         byte[] l3LastIPv6Bytes = Arrays.copyOfRange(l3.getAddress().getAddress(), 12, 16);
    275         assertTrue(Arrays.equals(ipv4Bytes, l2FirstIPv6Bytes));
    276         assertTrue(Arrays.equals(ipv4Bytes, l3LastIPv6Bytes));
    277 
    278         assertLinkAddressesNotEqual(l1, l2);
    279         assertIsNotSameAddressAs(l1, l2);
    280 
    281         assertLinkAddressesNotEqual(l1, l3);
    282         assertIsNotSameAddressAs(l1, l3);
    283 
    284         // Because we use InetAddress, an IPv4 address is equal to its IPv4-mapped address.
    285         // TODO: Investigate fixing this.
    286         String addressString = V4 + "/24";
    287         l1 = new LinkAddress(addressString);
    288         l2 = new LinkAddress("::ffff:" + addressString);
    289         assertLinkAddressesEqual(l1, l2);
    290         assertIsSameAddressAs(l1, l2);
    291     }
    292 
    293     public void testHashCode() {
    294         LinkAddress l;
    295 
    296         l = new LinkAddress(V4_ADDRESS, 23);
    297         assertEquals(-982787, l.hashCode());
    298 
    299         l = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST);
    300         assertEquals(-971865, l.hashCode());
    301 
    302         l = new LinkAddress(V4_ADDRESS, 27);
    303         assertEquals(-982743, l.hashCode());
    304 
    305         l = new LinkAddress(V6_ADDRESS, 64);
    306         assertEquals(1076522926, l.hashCode());
    307 
    308         l = new LinkAddress(V6_ADDRESS, 128);
    309         assertEquals(1076523630, l.hashCode());
    310 
    311         l = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE);
    312         assertEquals(1076524846, l.hashCode());
    313     }
    314 
    315     private LinkAddress passThroughParcel(LinkAddress l) {
    316         Parcel p = Parcel.obtain();
    317         LinkAddress l2 = null;
    318         try {
    319             l.writeToParcel(p, 0);
    320             p.setDataPosition(0);
    321             l2 = LinkAddress.CREATOR.createFromParcel(p);
    322         } finally {
    323             p.recycle();
    324         }
    325         assertNotNull(l2);
    326         return l2;
    327     }
    328 
    329     private void assertParcelingIsLossless(LinkAddress l) {
    330       LinkAddress l2 = passThroughParcel(l);
    331       assertEquals(l, l2);
    332     }
    333 
    334     public void testParceling() {
    335         LinkAddress l;
    336 
    337         l = new LinkAddress(V6_ADDRESS, 64, 123, 456);
    338         assertParcelingIsLossless(l);
    339 
    340         l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
    341         assertParcelingIsLossless(l);
    342     }
    343 }
    344