1a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline/* 2a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * Copyright (C) 2016 The Android Open Source Project 3a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * 4a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * Licensed under the Apache License, Version 2.0 (the "License"); 5a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * you may not use this file except in compliance with the License. 6a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * You may obtain a copy of the License at 7a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * 8a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * http://www.apache.org/licenses/LICENSE-2.0 9a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * 10a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * Unless required by applicable law or agreed to in writing, software 11a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * distributed under the License is distributed on an "AS IS" BASIS, 12a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * See the License for the specific language governing permissions and 14a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * limitations under the License. 15a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 16a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 17a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klinepackage android.net.ip; 18a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 195f2b7992cfe1149de115c6f7056d0da128b8afbaErik Klineimport static android.net.util.NetworkConstants.IPV6_MIN_MTU; 205f2b7992cfe1149de115c6f7056d0da128b8afbaErik Klineimport static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH; 21a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport static android.system.OsConstants.*; 22a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 23a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.net.IpPrefix; 24a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.net.LinkAddress; 25a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.net.LinkProperties; 26a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.net.NetworkUtils; 27619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkeyimport android.net.TrafficStats; 28a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.system.ErrnoException; 29a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.system.Os; 30a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.system.StructGroupReq; 31a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.system.StructTimeval; 32a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport android.util.Log; 33a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 34a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport com.android.internal.annotations.GuardedBy; 35a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 36e33daf12957417547efb7896aa81c1289eb80b81Erik Klineimport libcore.io.IoBridge; 37a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport libcore.util.HexEncoding; 38a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 39a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.io.FileDescriptor; 40a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.io.InterruptedIOException; 41a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.io.IOException; 42a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.net.Inet6Address; 43a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.net.InetAddress; 44a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.net.InetSocketAddress; 45a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.net.SocketException; 46a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.net.UnknownHostException; 47a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.nio.BufferOverflowException; 48a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.nio.ByteBuffer; 49a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.nio.ByteOrder; 50a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.util.ArrayList; 51354607f2acbe5e54c28369db36cf14fd7c548467Erik Klineimport java.util.HashMap; 52a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.util.HashSet; 53fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Klineimport java.util.Iterator; 54354607f2acbe5e54c28369db36cf14fd7c548467Erik Klineimport java.util.Map; 55a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.util.Random; 56a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.util.Set; 57a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klineimport java.util.concurrent.atomic.AtomicInteger; 58a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 59a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 60a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline/** 61a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * Basic IPv6 Router Advertisement Daemon. 62a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * 63a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * TODO: 64a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * 65a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * - Rewrite using Handler (and friends) so that AlarmManager can deliver 66a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * "kick" messages when it's time to send a multicast RA. 67a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * 68a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline * @hide 69a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 70a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Klinepublic class RouterAdvertisementDaemon { 71a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final String TAG = RouterAdvertisementDaemon.class.getSimpleName(); 72a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final byte ICMPV6_ND_ROUTER_SOLICIT = asByte(133); 73a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final byte ICMPV6_ND_ROUTER_ADVERT = asByte(134); 74a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final int MIN_RA_HEADER_SIZE = 16; 75a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 76a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Summary of various timers and lifetimes. 77a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final int MIN_RTR_ADV_INTERVAL_SEC = 300; 78a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final int MAX_RTR_ADV_INTERVAL_SEC = 600; 79a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // In general, router, prefix, and DNS lifetimes are all advised to be 80a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL. Here, we double 81a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // that to allow for multicast packet loss. 82a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // 83a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // This MAX_RTR_ADV_INTERVAL_SEC and DEFAULT_LIFETIME are also consistent 84a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // with the https://tools.ietf.org/html/rfc7772#section-4 discussion of 85a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // "approximately 7 RAs per hour". 86a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final int DEFAULT_LIFETIME = 6 * MAX_RTR_ADV_INTERVAL_SEC; 87a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // From https://tools.ietf.org/html/rfc4861#section-10 . 88a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final int MIN_DELAY_BETWEEN_RAS_SEC = 3; 89a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Both initial and final RAs, but also for changes in RA contents. 90a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // From https://tools.ietf.org/html/rfc4861#section-10 . 91a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final int MAX_URGENT_RTR_ADVERTISEMENTS = 5; 92a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 93a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final int DAY_IN_SECONDS = 86_400; 94a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 95a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static final byte[] ALL_NODES = new byte[] { 96a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 97a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline }; 98a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 99a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final String mIfName; 100a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final int mIfIndex; 101a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final byte[] mHwAddr; 102a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final InetSocketAddress mAllNodes; 103a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 104a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // This lock is to protect the RA from being updated while being 105a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // transmitted on another thread (multicast or unicast). 106a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // 107a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // TODO: This should be handled with a more RCU-like approach. 108a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final Object mLock = new Object(); 109a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline @GuardedBy("mLock") 110a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final byte[] mRA = new byte[IPV6_MIN_MTU]; 111a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline @GuardedBy("mLock") 112a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private int mRaLength; 113354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline @GuardedBy("mLock") 114fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline private final DeprecatedInfoTracker mDeprecatedInfoTracker; 115354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline @GuardedBy("mLock") 116354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline private RaParams mRaParams; 117a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 118a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private volatile FileDescriptor mSocket; 119a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private volatile MulticastTransmitter mMulticastTransmitter; 120a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private volatile UnicastResponder mUnicastResponder; 121a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 122a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public static class RaParams { 123a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public boolean hasDefaultRoute; 124a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public int mtu; 125a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public HashSet<IpPrefix> prefixes; 126a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public HashSet<Inet6Address> dnses; 127a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 128a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public RaParams() { 129a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline hasDefaultRoute = false; 130a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mtu = IPV6_MIN_MTU; 131a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline prefixes = new HashSet<IpPrefix>(); 132a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline dnses = new HashSet<Inet6Address>(); 133a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 134a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 135a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public RaParams(RaParams other) { 136a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline hasDefaultRoute = other.hasDefaultRoute; 137a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mtu = other.mtu; 138a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline prefixes = (HashSet) other.prefixes.clone(); 139a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline dnses = (HashSet) other.dnses.clone(); 140a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 141fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 142fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // Returns the subset of RA parameters that become deprecated when 143fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // moving from announcing oldRa to announcing newRa. 144fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // 145fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // Currently only tracks differences in |prefixes| and |dnses|. 146fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline public static RaParams getDeprecatedRaParams(RaParams oldRa, RaParams newRa) { 147fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline RaParams newlyDeprecated = new RaParams(); 148fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 149fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (oldRa != null) { 150fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline for (IpPrefix ipp : oldRa.prefixes) { 151fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (newRa == null || !newRa.prefixes.contains(ipp)) { 152fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline newlyDeprecated.prefixes.add(ipp); 153fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 154fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 155fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 156fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline for (Inet6Address dns : oldRa.dnses) { 157fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (newRa == null || !newRa.dnses.contains(dns)) { 158fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline newlyDeprecated.dnses.add(dns); 159fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 160fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 161fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 162fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 163fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline return newlyDeprecated; 164fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 165fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 166fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 167fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline private static class DeprecatedInfoTracker { 168fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline private final HashMap<IpPrefix, Integer> mPrefixes = new HashMap<>(); 169fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline private final HashMap<Inet6Address, Integer> mDnses = new HashMap<>(); 170fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 171fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline Set<IpPrefix> getPrefixes() { return mPrefixes.keySet(); } 172fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 173fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline void putPrefixes(Set<IpPrefix> prefixes) { 174fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline for (IpPrefix ipp : prefixes) { 175fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mPrefixes.put(ipp, MAX_URGENT_RTR_ADVERTISEMENTS); 176fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 177fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 178fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 179fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline void removePrefixes(Set<IpPrefix> prefixes) { 180fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline for (IpPrefix ipp : prefixes) { 181fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mPrefixes.remove(ipp); 182fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 183fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 184fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 185fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline Set<Inet6Address> getDnses() { return mDnses.keySet(); } 186fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 187fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline void putDnses(Set<Inet6Address> dnses) { 188fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline for (Inet6Address dns : dnses) { 189fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mDnses.put(dns, MAX_URGENT_RTR_ADVERTISEMENTS); 190fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 191fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 192fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 193fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline void removeDnses(Set<Inet6Address> dnses) { 194fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline for (Inet6Address dns : dnses) { 195fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mDnses.remove(dns); 196fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 197fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 198fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 199fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline boolean isEmpty() { return mPrefixes.isEmpty() && mDnses.isEmpty(); } 200fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 201fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline private boolean decrementCounters() { 202fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline boolean removed = decrementCounter(mPrefixes); 203fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline removed |= decrementCounter(mDnses); 204fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline return removed; 205fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 206fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 207fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline private <T> boolean decrementCounter(HashMap<T, Integer> map) { 208fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline boolean removed = false; 209fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 210fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline for (Iterator<Map.Entry<T, Integer>> it = map.entrySet().iterator(); 211fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline it.hasNext();) { 212fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline Map.Entry<T, Integer> kv = it.next(); 213fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (kv.getValue() == 0) { 214fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline it.remove(); 215fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline removed = true; 216fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } else { 217fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline kv.setValue(kv.getValue() - 1); 218fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 219fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 220fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 221fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline return removed; 222fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 223a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 224a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 225a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 226a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public RouterAdvertisementDaemon(String ifname, int ifindex, byte[] hwaddr) { 227a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mIfName = ifname; 228a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mIfIndex = ifindex; 229a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mHwAddr = hwaddr; 230a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0); 231fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mDeprecatedInfoTracker = new DeprecatedInfoTracker(); 232a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 233a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 234fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline public void buildNewRa(RaParams deprecatedParams, RaParams newParams) { 235fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline synchronized (mLock) { 236fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (deprecatedParams != null) { 237fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mDeprecatedInfoTracker.putPrefixes(deprecatedParams.prefixes); 238fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mDeprecatedInfoTracker.putDnses(deprecatedParams.dnses); 239354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline } 240354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 241fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (newParams != null) { 242fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // Process information that is no longer deprecated. 243fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mDeprecatedInfoTracker.removePrefixes(newParams.prefixes); 244fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mDeprecatedInfoTracker.removeDnses(newParams.dnses); 245fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 246a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 247fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mRaParams = newParams; 248fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline assembleRaLocked(); 249a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 250a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 251a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline maybeNotifyMulticastTransmitter(); 252a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 253a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 254a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public boolean start() { 255a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (!createSocket()) { 256a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return false; 257a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 258a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 259a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mMulticastTransmitter = new MulticastTransmitter(); 260a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mMulticastTransmitter.start(); 261a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 262a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mUnicastResponder = new UnicastResponder(); 263a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mUnicastResponder.start(); 264a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 265a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return true; 266a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 267a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 268a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public void stop() { 269a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline closeSocket(); 270a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mMulticastTransmitter = null; 271a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mUnicastResponder = null; 272a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 273a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 274fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline private void assembleRaLocked() { 275354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline final ByteBuffer ra = ByteBuffer.wrap(mRA); 276354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline ra.order(ByteOrder.BIG_ENDIAN); 277354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 278fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline boolean shouldSendRA = false; 279354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 280fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline try { 281fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline putHeader(ra, mRaParams != null && mRaParams.hasDefaultRoute); 282fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline putSlla(ra, mHwAddr); 283fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mRaLength = ra.position(); 284fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 285fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // https://tools.ietf.org/html/rfc5175#section-4 says: 286fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // 287fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // "MUST NOT be added to a Router Advertisement message 288fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // if no flags in the option are set." 289fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // 290fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // putExpandedFlagsOption(ra); 291fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline 292fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (mRaParams != null) { 293354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline putMtu(ra, mRaParams.mtu); 294fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mRaLength = ra.position(); 295354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 296354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline for (IpPrefix ipp : mRaParams.prefixes) { 297354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline putPio(ra, ipp, DEFAULT_LIFETIME, DEFAULT_LIFETIME); 298fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mRaLength = ra.position(); 299fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline shouldSendRA = true; 300354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline } 301354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 302354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline if (mRaParams.dnses.size() > 0) { 303fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline putRdnss(ra, mRaParams.dnses, DEFAULT_LIFETIME); 304fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mRaLength = ra.position(); 305fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline shouldSendRA = true; 306354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline } 307fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 308354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 309fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline for (IpPrefix ipp : mDeprecatedInfoTracker.getPrefixes()) { 310fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline putPio(ra, ipp, 0, 0); 311354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline mRaLength = ra.position(); 312fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline shouldSendRA = true; 313354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline } 314354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 315fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline final Set<Inet6Address> deprecatedDnses = mDeprecatedInfoTracker.getDnses(); 316fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (!deprecatedDnses.isEmpty()) { 317fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline putRdnss(ra, deprecatedDnses, 0); 318fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mRaLength = ra.position(); 319fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline shouldSendRA = true; 320354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline } 321fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } catch (BufferOverflowException e) { 322fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // The packet up to mRaLength is valid, since it has been updated 323fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // progressively as the RA was built. Log an error, and continue 324fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // on as best as possible. 325fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline Log.e(TAG, "Could not construct new RA: " + e); 326354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline } 327354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 328fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // We have nothing worth announcing; indicate as much to maybeSendRA(). 329fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (!shouldSendRA) { 330fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline mRaLength = 0; 331fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 332354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline } 333354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 334a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private void maybeNotifyMulticastTransmitter() { 335a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final MulticastTransmitter m = mMulticastTransmitter; 336a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (m != null) { 337a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline m.hup(); 338a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 339a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 340a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 341a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static Inet6Address getAllNodesForScopeId(int scopeId) { 342a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline try { 343a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return Inet6Address.getByAddress("ff02::1", ALL_NODES, scopeId); 344a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } catch (UnknownHostException uhe) { 345a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Log.wtf(TAG, "Failed to construct ff02::1 InetAddress: " + uhe); 346a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return null; 347a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 348a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 349a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 350a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static byte asByte(int value) { return (byte) value; } 351a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static short asShort(int value) { return (short) value; } 352a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 353a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute) { 354a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline /** 355a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Router Advertisement Message Format 356a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 357a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 358a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 359a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 360a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Type | Code | Checksum | 361a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 362a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Cur Hop Limit |M|O|H|Prf|P|R|R| Router Lifetime | 363a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 364a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Reachable Time | 365a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 366a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Retrans Timer | 367a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 368a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Options ... 369a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+- 370a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 371a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte DEFAULT_HOPLIMIT = 64; 372a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(ICMPV6_ND_ROUTER_ADVERT) 373a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(asByte(0)) 374a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putShort(asShort(0)) 375a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(DEFAULT_HOPLIMIT) 376a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // RFC 4191 "high" preference, iff. advertising a default route. 377a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(hasDefaultRoute ? asByte(0x08) : asByte(0)) 378a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putShort(hasDefaultRoute ? asShort(DEFAULT_LIFETIME) : asShort(0)) 379a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putInt(0) 380a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putInt(0); 381a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 382a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 383a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static void putSlla(ByteBuffer ra, byte[] slla) { 384a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline /** 385a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Source/Target Link-layer Address 386a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 387a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 388a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 389a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 390a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Type | Length | Link-Layer Address ... 391a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 392a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 393a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (slla == null || slla.length != 6) { 394a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Only IEEE 802.3 6-byte addresses are supported. 395a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return; 396a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 397a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte ND_OPTION_SLLA = 1; 398a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte SLLA_NUM_8OCTETS = 1; 399a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(ND_OPTION_SLLA) 400a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(SLLA_NUM_8OCTETS) 401a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(slla); 402a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 403a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 404a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static void putExpandedFlagsOption(ByteBuffer ra) { 405a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline /** 406a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Router Advertisement Expanded Flags Option 407a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 408a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 409a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 410a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 411a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Type | Length | Bit fields available .. 412a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 413a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ... for assignment | 414a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 415a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 416a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 417a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte ND_OPTION_EFO = 26; 418a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte EFO_NUM_8OCTETS = 1; 419a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 420a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(ND_OPTION_EFO) 421a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(EFO_NUM_8OCTETS) 422a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putShort(asShort(0)) 423a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putInt(0); 424a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 425a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 426a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static void putMtu(ByteBuffer ra, int mtu) { 427a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline /** 428a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline MTU 429a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 430a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 431a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 432a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 433a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Type | Length | Reserved | 434a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 435a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | MTU | 436a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 437a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 438a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte ND_OPTION_MTU = 5; 439a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte MTU_NUM_8OCTETS = 1; 440a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(ND_OPTION_MTU) 441a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(MTU_NUM_8OCTETS) 442a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putShort(asShort(0)) 443354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline .putInt((mtu < IPV6_MIN_MTU) ? IPV6_MIN_MTU : mtu); 444a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 445a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 446354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline private static void putPio(ByteBuffer ra, IpPrefix ipp, 447354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline int validTime, int preferredTime) { 448a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline /** 449a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Prefix Information 450a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 451a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 452a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 453a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 454a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Type | Length | Prefix Length |L|A| Reserved1 | 455a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 456a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Valid Lifetime | 457a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 458a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Preferred Lifetime | 459a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 460a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Reserved2 | 461a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 462a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | | 463a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline + + 464a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | | 465a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline + Prefix + 466a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | | 467a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline + + 468a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | | 469a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 470a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 471a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final int prefixLength = ipp.getPrefixLength(); 472a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (prefixLength != 64) { 473a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return; 474a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 475a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte ND_OPTION_PIO = 3; 476a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte PIO_NUM_8OCTETS = 4; 477a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 478354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline if (validTime < 0) validTime = 0; 479354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline if (preferredTime < 0) preferredTime = 0; 480354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline if (preferredTime > validTime) preferredTime = validTime; 481354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline 482a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte[] addr = ipp.getAddress().getAddress(); 483a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(ND_OPTION_PIO) 484a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(PIO_NUM_8OCTETS) 485a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(asByte(prefixLength)) 486354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline .put(asByte(0xc0)) /* L & A set */ 487354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline .putInt(validTime) 488354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline .putInt(preferredTime) 489a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putInt(0) 490a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(addr); 491a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 492a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 493a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private static void putRio(ByteBuffer ra, IpPrefix ipp) { 494a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline /** 495a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Route Information Option 496a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 497a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 498a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 499a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 500a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Type | Length | Prefix Length |Resvd|Prf|Resvd| 501a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 502a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Route Lifetime | 503a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 504a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Prefix (Variable Length) | 505a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline . . 506a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline . . 507a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 508a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 509a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final int prefixLength = ipp.getPrefixLength(); 510a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (prefixLength > 64) { 511a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return; 512a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 513a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte ND_OPTION_RIO = 24; 514a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte RIO_NUM_8OCTETS = asByte( 515a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline (prefixLength == 0) ? 1 : (prefixLength <= 8) ? 2 : 3); 516a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 517a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte[] addr = ipp.getAddress().getAddress(); 518a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(ND_OPTION_RIO) 519a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(RIO_NUM_8OCTETS) 520a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(asByte(prefixLength)) 521a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(asByte(0x18)) 522a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putInt(DEFAULT_LIFETIME); 523a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 524a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Rely upon an IpPrefix's address being properly zeroed. 525a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (prefixLength > 0) { 526a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(addr, 0, (prefixLength <= 64) ? 8 : 16); 527a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 528a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 529a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 530fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline private static void putRdnss(ByteBuffer ra, Set<Inet6Address> dnses, int lifetime) { 531a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline /** 532a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Recursive DNS Server (RDNSS) Option 533a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 534a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 535a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 536a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 537a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Type | Length | Reserved | 538a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 539a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | Lifetime | 540a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 541a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | | 542a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline : Addresses of IPv6 Recursive DNS Servers : 543a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline | | 544a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 545a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline */ 546a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 5475f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline final HashSet<Inet6Address> filteredDnses = new HashSet<>(); 5485f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline for (Inet6Address dns : dnses) { 5495f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline if ((new LinkAddress(dns, RFC7421_PREFIX_LENGTH)).isGlobalPreferred()) { 5505f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline filteredDnses.add(dns); 5515f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline } 5525f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline } 5535f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline if (filteredDnses.isEmpty()) return; 5545f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline 555a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte ND_OPTION_RDNSS = 25; 556a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final byte RDNSS_NUM_8OCTETS = asByte(dnses.size() * 2 + 1); 557a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(ND_OPTION_RDNSS) 558a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .put(RDNSS_NUM_8OCTETS) 559a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline .putShort(asShort(0)) 560fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline .putInt(lifetime); 561a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 5625f2b7992cfe1149de115c6f7056d0da128b8afbaErik Kline for (Inet6Address dns : filteredDnses) { 563fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // NOTE: If the full of list DNS servers doesn't fit in the packet, 564fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // this code will cause a buffer overflow and the RA won't include 565d1dcbefe06acccba3da2f262d3f4867a3814456cErik Kline // this instance of the option at all. 566fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // 567fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // TODO: Consider looking at ra.remaining() to determine how many 568fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // DNS servers will fit, and adding only those. 569a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline ra.put(dns.getAddress()); 570a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 571a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 572a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 573a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private boolean createSocket() { 574a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final int SEND_TIMEOUT_MS = 300; 575a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 576619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkey final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NEIGHBOR); 577a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline try { 578a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 579a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Setting SNDTIMEO is purely for defensive purposes. 580a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Os.setsockoptTimeval( 581a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS)); 582a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mIfName); 583a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline NetworkUtils.protectFromVpn(mSocket); 584a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline NetworkUtils.setupRaSocket(mSocket, mIfIndex); 585a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } catch (ErrnoException | IOException e) { 586a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Log.e(TAG, "Failed to create RA daemon socket: " + e); 587a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return false; 588619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkey } finally { 589619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkey TrafficStats.setThreadStatsTag(oldTag); 590a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 591a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 592a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return true; 593a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 594a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 595a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private void closeSocket() { 596a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (mSocket != null) { 597e33daf12957417547efb7896aa81c1289eb80b81Erik Kline try { 598e33daf12957417547efb7896aa81c1289eb80b81Erik Kline IoBridge.closeAndSignalBlockedThreads(mSocket); 599e33daf12957417547efb7896aa81c1289eb80b81Erik Kline } catch (IOException ignored) {} 600a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 601a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mSocket = null; 602a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 603a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 604a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private boolean isSocketValid() { 605a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final FileDescriptor s = mSocket; 606a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return (s != null) && s.valid(); 607a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 608a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 609a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private boolean isSuitableDestination(InetSocketAddress dest) { 610a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (mAllNodes.equals(dest)) { 611a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return true; 612a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 613a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 614a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final InetAddress destip = dest.getAddress(); 615a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return (destip instanceof Inet6Address) && 616a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline destip.isLinkLocalAddress() && 617a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline (((Inet6Address) destip).getScopeId() == mIfIndex); 618a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 619a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 620a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private void maybeSendRA(InetSocketAddress dest) { 621a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (dest == null || !isSuitableDestination(dest)) { 622a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline dest = mAllNodes; 623a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 624a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 625a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline try { 626a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline synchronized (mLock) { 627a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (mRaLength < MIN_RA_HEADER_SIZE) { 628a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // No actual RA to send. 629a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return; 630a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 631a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Os.sendto(mSocket, mRA, 0, mRaLength, 0, dest); 632a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 633a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Log.d(TAG, "RA sendto " + dest.getAddress().getHostAddress()); 634a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } catch (ErrnoException | SocketException e) { 635a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (isSocketValid()) { 636a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Log.e(TAG, "sendto error: " + e); 637a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 638a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 639a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 640a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 641a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final class UnicastResponder extends Thread { 642a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final InetSocketAddress solicitor = new InetSocketAddress(); 643a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // The recycled buffer for receiving Router Solicitations from clients. 644a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // If the RS is larger than IPV6_MIN_MTU the packets are truncated. 645a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // This is fine since currently only byte 0 is examined anyway. 646a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final byte mSolication[] = new byte[IPV6_MIN_MTU]; 647a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 648a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline @Override 649a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public void run() { 650a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline while (isSocketValid()) { 651a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline try { 652a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Blocking receive. 653a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final int rval = Os.recvfrom( 654a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mSocket, mSolication, 0, mSolication.length, 0, solicitor); 655a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Do the least possible amount of validation. 656a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (rval < 1 || mSolication[0] != ICMPV6_ND_ROUTER_SOLICIT) { 657a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline continue; 658a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 659a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } catch (ErrnoException | SocketException e) { 660a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (isSocketValid()) { 661a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Log.e(TAG, "recvfrom error: " + e); 662a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 663a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline continue; 664a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 665a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 666a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline maybeSendRA(solicitor); 667a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 668a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 669a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 670a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 671a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // TODO: Consider moving this to run on a provided Looper as a Handler, 672a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // with WakeupMessage-style messages providing the timer driven input. 673a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final class MulticastTransmitter extends Thread { 674a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final Random mRandom = new Random(); 675a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private final AtomicInteger mUrgentAnnouncements = new AtomicInteger(0); 676a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 677a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline @Override 678a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public void run() { 679a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline while (isSocketValid()) { 680a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline try { 681a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline Thread.sleep(getNextMulticastTransmitDelayMs()); 682a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } catch (InterruptedException ignored) { 683a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Stop sleeping, immediately send an RA, and continue. 684a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 685a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 686a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline maybeSendRA(mAllNodes); 687fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline synchronized (mLock) { 688fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if (mDeprecatedInfoTracker.decrementCounters()) { 689fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // At least one deprecated PIO has been removed; 690fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline // reassemble the RA. 691fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline assembleRaLocked(); 692fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline } 693354607f2acbe5e54c28369db36cf14fd7c548467Erik Kline } 694a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 695a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 696a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 697a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline public void hup() { 698a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // Set to one fewer that the desired number, because as soon as 699a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // the thread interrupt is processed we immediately send an RA 700a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // and mUrgentAnnouncements is not examined until the subsequent 701a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // sleep interval computation (i.e. this way we send 3 and not 4). 702a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline mUrgentAnnouncements.set(MAX_URGENT_RTR_ADVERTISEMENTS - 1); 703a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline interrupt(); 704a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 705a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 706a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private int getNextMulticastTransmitDelaySec() { 707fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline boolean deprecationInProgress = false; 708a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline synchronized (mLock) { 709a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline if (mRaLength < MIN_RA_HEADER_SIZE) { 710a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline // No actual RA to send; just sleep for 1 day. 711a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return DAY_IN_SECONDS; 712a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 713fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline deprecationInProgress = !mDeprecatedInfoTracker.isEmpty(); 714a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 715a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 716a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline final int urgentPending = mUrgentAnnouncements.getAndDecrement(); 717fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline if ((urgentPending > 0) || deprecationInProgress) { 718a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return MIN_DELAY_BETWEEN_RAS_SEC; 719a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 720a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 721a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return MIN_RTR_ADV_INTERVAL_SEC + mRandom.nextInt( 722a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline MAX_RTR_ADV_INTERVAL_SEC - MIN_RTR_ADV_INTERVAL_SEC); 723a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 724a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline 725a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline private long getNextMulticastTransmitDelayMs() { 726a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline return 1000 * (long) getNextMulticastTransmitDelaySec(); 727a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 728a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline } 729a3ca6bd3e03a5311b37e4c1c7a9e8625e53d78b3Erik Kline} 730