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_DADFAILED;
     37 import static android.system.OsConstants.IFA_F_DEPRECATED;
     38 import static android.system.OsConstants.IFA_F_OPTIMISTIC;
     39 import static android.system.OsConstants.IFA_F_PERMANENT;
     40 import static android.system.OsConstants.IFA_F_TEMPORARY;
     41 import static android.system.OsConstants.IFA_F_TENTATIVE;
     42 import static android.system.OsConstants.RT_SCOPE_HOST;
     43 import static android.system.OsConstants.RT_SCOPE_LINK;
     44 import static android.system.OsConstants.RT_SCOPE_SITE;
     45 import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
     46 
     47 /**
     48  * Tests for {@link LinkAddress}.
     49  */
     50 public class LinkAddressTest extends AndroidTestCase {
     51 
     52     private static final String V4 = "192.0.2.1";
     53     private static final String V6 = "2001:db8::1";
     54     private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
     55     private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);
     56 
     57     public void testConstants() {
     58         // RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero.
     59         assertNotEqual(0, RT_SCOPE_HOST);
     60         assertNotEqual(0, RT_SCOPE_LINK);
     61         assertNotEqual(0, RT_SCOPE_SITE);
     62 
     63         assertNotEqual(0, IFA_F_DEPRECATED);
     64         assertNotEqual(0, IFA_F_PERMANENT);
     65         assertNotEqual(0, IFA_F_TENTATIVE);
     66     }
     67 
     68     public void testConstructors() throws SocketException {
     69         LinkAddress address;
     70 
     71         // Valid addresses work as expected.
     72         address = new LinkAddress(V4_ADDRESS, 25);
     73         assertEquals(V4_ADDRESS, address.getAddress());
     74         assertEquals(25, address.getPrefixLength());
     75         assertEquals(0, address.getFlags());
     76         assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
     77 
     78         address = new LinkAddress(V6_ADDRESS, 127);
     79         assertEquals(V6_ADDRESS, address.getAddress());
     80         assertEquals(127, address.getPrefixLength());
     81         assertEquals(0, address.getFlags());
     82         assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
     83 
     84         // Nonsensical flags/scopes or combinations thereof are acceptable.
     85         address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK);
     86         assertEquals(V6_ADDRESS, address.getAddress());
     87         assertEquals(64, address.getPrefixLength());
     88         assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags());
     89         assertEquals(RT_SCOPE_LINK, address.getScope());
     90 
     91         address = new LinkAddress(V4 + "/23", 123, 456);
     92         assertEquals(V4_ADDRESS, address.getAddress());
     93         assertEquals(23, address.getPrefixLength());
     94         assertEquals(123, address.getFlags());
     95         assertEquals(456, address.getScope());
     96 
     97         // InterfaceAddress doesn't have a constructor. Fetch some from an interface.
     98         List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses();
     99 
    100         // We expect to find 127.0.0.1/8 and ::1/128, in any order.
    101         LinkAddress ipv4Loopback, ipv6Loopback;
    102         assertEquals(2, addrs.size());
    103         if (addrs.get(0).getAddress() instanceof Inet4Address) {
    104             ipv4Loopback = new LinkAddress(addrs.get(0));
    105             ipv6Loopback = new LinkAddress(addrs.get(1));
    106         } else {
    107             ipv4Loopback = new LinkAddress(addrs.get(1));
    108             ipv6Loopback = new LinkAddress(addrs.get(0));
    109         }
    110 
    111         assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress());
    112         assertEquals(8, ipv4Loopback.getPrefixLength());
    113 
    114         assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress());
    115         assertEquals(128, ipv6Loopback.getPrefixLength());
    116 
    117         // Null addresses are rejected.
    118         try {
    119             address = new LinkAddress(null, 24);
    120             fail("Null InetAddress should cause IllegalArgumentException");
    121         } catch(IllegalArgumentException expected) {}
    122 
    123         try {
    124             address = new LinkAddress((String) null, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    125             fail("Null string should cause IllegalArgumentException");
    126         } catch(IllegalArgumentException expected) {}
    127 
    128         try {
    129             address = new LinkAddress((InterfaceAddress) null);
    130             fail("Null string should cause NullPointerException");
    131         } catch(NullPointerException expected) {}
    132 
    133         // Invalid prefix lengths are rejected.
    134         try {
    135             address = new LinkAddress(V4_ADDRESS, -1);
    136             fail("Negative IPv4 prefix length should cause IllegalArgumentException");
    137         } catch(IllegalArgumentException expected) {}
    138 
    139         try {
    140             address = new LinkAddress(V6_ADDRESS, -1);
    141             fail("Negative IPv6 prefix length should cause IllegalArgumentException");
    142         } catch(IllegalArgumentException expected) {}
    143 
    144         try {
    145             address = new LinkAddress(V4_ADDRESS, 33);
    146             fail("/33 IPv4 prefix length should cause IllegalArgumentException");
    147         } catch(IllegalArgumentException expected) {}
    148 
    149         try {
    150             address = new LinkAddress(V4 + "/33", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    151             fail("/33 IPv4 prefix length should cause IllegalArgumentException");
    152         } catch(IllegalArgumentException expected) {}
    153 
    154 
    155         try {
    156             address = new LinkAddress(V6_ADDRESS, 129, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    157             fail("/129 IPv6 prefix length should cause IllegalArgumentException");
    158         } catch(IllegalArgumentException expected) {}
    159 
    160         try {
    161             address = new LinkAddress(V6 + "/129", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    162             fail("/129 IPv6 prefix length should cause IllegalArgumentException");
    163         } catch(IllegalArgumentException expected) {}
    164 
    165         // Multicast addresses are rejected.
    166         try {
    167             address = new LinkAddress("224.0.0.2/32");
    168             fail("IPv4 multicast address should cause IllegalArgumentException");
    169         } catch(IllegalArgumentException expected) {}
    170 
    171         try {
    172             address = new LinkAddress("ff02::1/128");
    173             fail("IPv6 multicast address should cause IllegalArgumentException");
    174         } catch(IllegalArgumentException expected) {}
    175     }
    176 
    177     public void testAddressScopes() {
    178         assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope());
    179         assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope());
    180 
    181         assertEquals(RT_SCOPE_LINK, new LinkAddress("::1/128").getScope());
    182         assertEquals(RT_SCOPE_LINK, new LinkAddress("127.0.0.5/8").getScope());
    183         assertEquals(RT_SCOPE_LINK, new LinkAddress("fe80::ace:d00d/64").getScope());
    184         assertEquals(RT_SCOPE_LINK, new LinkAddress("169.254.5.12/16").getScope());
    185 
    186         assertEquals(RT_SCOPE_SITE, new LinkAddress("fec0::dead/64").getScope());
    187 
    188         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("10.1.2.3/21").getScope());
    189         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("192.0.2.1/25").getScope());
    190         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("2001:db8::/64").getScope());
    191         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("5000::/127").getScope());
    192     }
    193 
    194     private void assertIsSameAddressAs(LinkAddress l1, LinkAddress l2) {
    195         assertTrue(l1 + " unexpectedly does not have same address as " + l2,
    196                 l1.isSameAddressAs(l2));
    197         assertTrue(l2 + " unexpectedly does not have same address as " + l1,
    198                 l2.isSameAddressAs(l1));
    199     }
    200 
    201     private void assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2) {
    202         assertFalse(l1 + " unexpectedly has same address as " + l2,
    203                 l1.isSameAddressAs(l2));
    204         assertFalse(l2 + " unexpectedly has same address as " + l1,
    205                 l1.isSameAddressAs(l2));
    206     }
    207 
    208     private void assertLinkAddressesEqual(LinkAddress l1, LinkAddress l2) {
    209         assertTrue(l1 + " unexpectedly not equal to " + l2, l1.equals(l2));
    210         assertTrue(l2 + " unexpectedly not equal to " + l1, l2.equals(l1));
    211         assertEquals(l1.hashCode(), l2.hashCode());
    212     }
    213 
    214     private void assertLinkAddressesNotEqual(LinkAddress l1, LinkAddress l2) {
    215         assertFalse(l1 + " unexpectedly equal to " + l2, l1.equals(l2));
    216         assertFalse(l2 + " unexpectedly equal to " + l1, l2.equals(l1));
    217     }
    218 
    219     public void testEqualsAndSameAddressAs() {
    220         LinkAddress l1, l2, l3;
    221 
    222         l1 = new LinkAddress("2001:db8::1/64");
    223         l2 = new LinkAddress("2001:db8::1/64");
    224         assertLinkAddressesEqual(l1, l2);
    225         assertIsSameAddressAs(l1, l2);
    226 
    227         l2 = new LinkAddress("2001:db8::1/65");
    228         assertLinkAddressesNotEqual(l1, l2);
    229         assertIsNotSameAddressAs(l1, l2);
    230 
    231         l2 = new LinkAddress("2001:db8::2/64");
    232         assertLinkAddressesNotEqual(l1, l2);
    233         assertIsNotSameAddressAs(l1, l2);
    234 
    235 
    236         l1 = new LinkAddress("192.0.2.1/24");
    237         l2 = new LinkAddress("192.0.2.1/24");
    238         assertLinkAddressesEqual(l1, l2);
    239         assertIsSameAddressAs(l1, l2);
    240 
    241         l2 = new LinkAddress("192.0.2.1/23");
    242         assertLinkAddressesNotEqual(l1, l2);
    243         assertIsNotSameAddressAs(l1, l2);
    244 
    245         l2 = new LinkAddress("192.0.2.2/24");
    246         assertLinkAddressesNotEqual(l1, l2);
    247         assertIsNotSameAddressAs(l1, l2);
    248 
    249 
    250         // Check equals() and isSameAddressAs() on identical addresses with different flags.
    251         l1 = new LinkAddress(V6_ADDRESS, 64);
    252         l2 = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE);
    253         assertLinkAddressesEqual(l1, l2);
    254         assertIsSameAddressAs(l1, l2);
    255 
    256         l2 = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_UNIVERSE);
    257         assertLinkAddressesNotEqual(l1, l2);
    258         assertIsSameAddressAs(l1, l2);
    259 
    260         // Check equals() and isSameAddressAs() on identical addresses with different scope.
    261         l1 = new LinkAddress(V4_ADDRESS, 24);
    262         l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_UNIVERSE);
    263         assertLinkAddressesEqual(l1, l2);
    264         assertIsSameAddressAs(l1, l2);
    265 
    266         l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_HOST);
    267         assertLinkAddressesNotEqual(l1, l2);
    268         assertIsSameAddressAs(l1, l2);
    269 
    270         // Addresses with the same start or end bytes aren't equal between families.
    271         l1 = new LinkAddress("32.1.13.184/24");
    272         l2 = new LinkAddress("2001:db8::1/24");
    273         l3 = new LinkAddress("::2001:db8/24");
    274 
    275         byte[] ipv4Bytes = l1.getAddress().getAddress();
    276         byte[] l2FirstIPv6Bytes = Arrays.copyOf(l2.getAddress().getAddress(), 4);
    277         byte[] l3LastIPv6Bytes = Arrays.copyOfRange(l3.getAddress().getAddress(), 12, 16);
    278         assertTrue(Arrays.equals(ipv4Bytes, l2FirstIPv6Bytes));
    279         assertTrue(Arrays.equals(ipv4Bytes, l3LastIPv6Bytes));
    280 
    281         assertLinkAddressesNotEqual(l1, l2);
    282         assertIsNotSameAddressAs(l1, l2);
    283 
    284         assertLinkAddressesNotEqual(l1, l3);
    285         assertIsNotSameAddressAs(l1, l3);
    286 
    287         // Because we use InetAddress, an IPv4 address is equal to its IPv4-mapped address.
    288         // TODO: Investigate fixing this.
    289         String addressString = V4 + "/24";
    290         l1 = new LinkAddress(addressString);
    291         l2 = new LinkAddress("::ffff:" + addressString);
    292         assertLinkAddressesEqual(l1, l2);
    293         assertIsSameAddressAs(l1, l2);
    294     }
    295 
    296     public void testHashCode() {
    297         LinkAddress l;
    298 
    299         l = new LinkAddress(V4_ADDRESS, 23);
    300         assertEquals(-982787, l.hashCode());
    301 
    302         l = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST);
    303         assertEquals(-971865, l.hashCode());
    304 
    305         l = new LinkAddress(V4_ADDRESS, 27);
    306         assertEquals(-982743, l.hashCode());
    307 
    308         l = new LinkAddress(V6_ADDRESS, 64);
    309         assertEquals(1076522926, l.hashCode());
    310 
    311         l = new LinkAddress(V6_ADDRESS, 128);
    312         assertEquals(1076523630, l.hashCode());
    313 
    314         l = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE);
    315         assertEquals(1076524846, l.hashCode());
    316     }
    317 
    318     private LinkAddress passThroughParcel(LinkAddress l) {
    319         Parcel p = Parcel.obtain();
    320         LinkAddress l2 = null;
    321         try {
    322             l.writeToParcel(p, 0);
    323             p.setDataPosition(0);
    324             l2 = LinkAddress.CREATOR.createFromParcel(p);
    325         } finally {
    326             p.recycle();
    327         }
    328         assertNotNull(l2);
    329         return l2;
    330     }
    331 
    332     private void assertParcelingIsLossless(LinkAddress l) {
    333       LinkAddress l2 = passThroughParcel(l);
    334       assertEquals(l, l2);
    335     }
    336 
    337     public void testParceling() {
    338         LinkAddress l;
    339 
    340         l = new LinkAddress(V6_ADDRESS, 64, 123, 456);
    341         assertParcelingIsLossless(l);
    342 
    343         l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
    344         assertParcelingIsLossless(l);
    345     }
    346 
    347     private void assertGlobalPreferred(LinkAddress l, String msg) {
    348         assertTrue(msg, l.isGlobalPreferred());
    349     }
    350 
    351     private void assertNotGlobalPreferred(LinkAddress l, String msg) {
    352         assertFalse(msg, l.isGlobalPreferred());
    353     }
    354 
    355     public void testIsGlobalPreferred() {
    356         LinkAddress l;
    357 
    358         l = new LinkAddress(V4_ADDRESS, 32, 0, RT_SCOPE_UNIVERSE);
    359         assertGlobalPreferred(l, "v4,global,noflags");
    360 
    361         l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_UNIVERSE);
    362         assertGlobalPreferred(l, "v4-rfc1918,global,noflags");
    363 
    364         l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_SITE);
    365         assertNotGlobalPreferred(l, "v4-rfc1918,site-local,noflags");
    366 
    367         l = new LinkAddress("127.0.0.7/8", 0, RT_SCOPE_HOST);
    368         assertNotGlobalPreferred(l, "v4-localhost,node-local,noflags");
    369 
    370         l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE);
    371         assertGlobalPreferred(l, "v6,global,noflags");
    372 
    373         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
    374         assertGlobalPreferred(l, "v6,global,permanent");
    375 
    376         // IPv6 ULAs are not acceptable "global preferred" addresses.
    377         l = new LinkAddress("fc12::1/64", 0, RT_SCOPE_UNIVERSE);
    378         assertNotGlobalPreferred(l, "v6,ula1,noflags");
    379 
    380         l = new LinkAddress("fd34::1/64", 0, RT_SCOPE_UNIVERSE);
    381         assertNotGlobalPreferred(l, "v6,ula2,noflags");
    382 
    383         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_UNIVERSE);
    384         assertGlobalPreferred(l, "v6,global,tempaddr");
    385 
    386         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DADFAILED),
    387                             RT_SCOPE_UNIVERSE);
    388         assertNotGlobalPreferred(l, "v6,global,tempaddr+dadfailed");
    389 
    390         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DEPRECATED),
    391                             RT_SCOPE_UNIVERSE);
    392         assertNotGlobalPreferred(l, "v6,global,tempaddr+deprecated");
    393 
    394         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_SITE);
    395         assertNotGlobalPreferred(l, "v6,site-local,tempaddr");
    396 
    397         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_LINK);
    398         assertNotGlobalPreferred(l, "v6,link-local,tempaddr");
    399 
    400         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_HOST);
    401         assertNotGlobalPreferred(l, "v6,node-local,tempaddr");
    402 
    403         l = new LinkAddress("::1/128", IFA_F_PERMANENT, RT_SCOPE_HOST);
    404         assertNotGlobalPreferred(l, "v6-localhost,node-local,permanent");
    405 
    406         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_TENTATIVE),
    407                             RT_SCOPE_UNIVERSE);
    408         assertNotGlobalPreferred(l, "v6,global,tempaddr+tentative");
    409 
    410         l = new LinkAddress(V6_ADDRESS, 64,
    411                             (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC),
    412                             RT_SCOPE_UNIVERSE);
    413         assertGlobalPreferred(l, "v6,global,tempaddr+optimistic");
    414     }
    415 }
    416