/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.ip;

import static android.net.util.NetworkConstants.IPV6_MIN_MTU;
import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.IPPROTO_ICMPV6;
import static android.system.OsConstants.SOCK_RAW;
import static android.system.OsConstants.SOL_SOCKET;
import static android.system.OsConstants.SO_BINDTODEVICE;
import static android.system.OsConstants.SO_SNDTIMEO;

import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.NetworkUtils;
import android.net.TrafficStats;
import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructTimeval;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.TrafficStatsConstants;

import libcore.io.IoBridge;

import java.io.FileDescriptor;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * Basic IPv6 Router Advertisement Daemon.
 *
 * TODO:
 *
 *     - Rewrite using Handler (and friends) so that AlarmManager can deliver
 *       "kick" messages when it's time to send a multicast RA.
 *
 * @hide
 */
public class RouterAdvertisementDaemon {
    private static final String TAG = RouterAdvertisementDaemon.class.getSimpleName();
    private static final byte ICMPV6_ND_ROUTER_SOLICIT = asByte(133);
    private static final byte ICMPV6_ND_ROUTER_ADVERT  = asByte(134);
    private static final int MIN_RA_HEADER_SIZE = 16;

    // Summary of various timers and lifetimes.
    private static final int MIN_RTR_ADV_INTERVAL_SEC = 300;
    private static final int MAX_RTR_ADV_INTERVAL_SEC = 600;
    // In general, router, prefix, and DNS lifetimes are all advised to be
    // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL.  Here, we double
    // that to allow for multicast packet loss.
    //
    // This MAX_RTR_ADV_INTERVAL_SEC and DEFAULT_LIFETIME are also consistent
    // with the https://tools.ietf.org/html/rfc7772#section-4 discussion of
    // "approximately 7 RAs per hour".
    private static final int DEFAULT_LIFETIME = 6 * MAX_RTR_ADV_INTERVAL_SEC;
    // From https://tools.ietf.org/html/rfc4861#section-10 .
    private static final int MIN_DELAY_BETWEEN_RAS_SEC = 3;
    // Both initial and final RAs, but also for changes in RA contents.
    // From https://tools.ietf.org/html/rfc4861#section-10 .
    private static final int  MAX_URGENT_RTR_ADVERTISEMENTS = 5;

    private static final int DAY_IN_SECONDS = 86_400;

    private static final byte[] ALL_NODES = new byte[] {
            (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
    };

    private final InterfaceParams mInterface;
    private final InetSocketAddress mAllNodes;

    // This lock is to protect the RA from being updated while being
    // transmitted on another thread  (multicast or unicast).
    //
    // TODO: This should be handled with a more RCU-like approach.
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private final byte[] mRA = new byte[IPV6_MIN_MTU];
    @GuardedBy("mLock")
    private int mRaLength;
    @GuardedBy("mLock")
    private final DeprecatedInfoTracker mDeprecatedInfoTracker;
    @GuardedBy("mLock")
    private RaParams mRaParams;

    private volatile FileDescriptor mSocket;
    private volatile MulticastTransmitter mMulticastTransmitter;
    private volatile UnicastResponder mUnicastResponder;

    public static class RaParams {
        // Tethered traffic will have the hop limit properly decremented.
        // Consequently, set the hoplimit greater by one than the upstream
        // unicast hop limit.
        //
        // TODO: Dynamically pass down the IPV6_UNICAST_HOPS value from the
        // upstream interface for more correct behaviour.
        static final byte DEFAULT_HOPLIMIT = 65;

        public boolean hasDefaultRoute;
        public byte hopLimit;
        public int mtu;
        public HashSet<IpPrefix> prefixes;
        public HashSet<Inet6Address> dnses;

        public RaParams() {
            hasDefaultRoute = false;
            hopLimit = DEFAULT_HOPLIMIT;
            mtu = IPV6_MIN_MTU;
            prefixes = new HashSet<IpPrefix>();
            dnses = new HashSet<Inet6Address>();
        }

        public RaParams(RaParams other) {
            hasDefaultRoute = other.hasDefaultRoute;
            hopLimit = other.hopLimit;
            mtu = other.mtu;
            prefixes = (HashSet) other.prefixes.clone();
            dnses = (HashSet) other.dnses.clone();
        }

        // Returns the subset of RA parameters that become deprecated when
        // moving from announcing oldRa to announcing newRa.
        //
        // Currently only tracks differences in |prefixes| and |dnses|.
        public static RaParams getDeprecatedRaParams(RaParams oldRa, RaParams newRa) {
            RaParams newlyDeprecated = new RaParams();

            if (oldRa != null) {
                for (IpPrefix ipp : oldRa.prefixes) {
                    if (newRa == null || !newRa.prefixes.contains(ipp)) {
                        newlyDeprecated.prefixes.add(ipp);
                    }
                }

                for (Inet6Address dns : oldRa.dnses) {
                    if (newRa == null || !newRa.dnses.contains(dns)) {
                        newlyDeprecated.dnses.add(dns);
                    }
                }
            }

            return newlyDeprecated;
        }
    }

    private static class DeprecatedInfoTracker {
        private final HashMap<IpPrefix, Integer> mPrefixes = new HashMap<>();
        private final HashMap<Inet6Address, Integer> mDnses = new HashMap<>();

        Set<IpPrefix> getPrefixes() { return mPrefixes.keySet(); }

        void putPrefixes(Set<IpPrefix> prefixes) {
            for (IpPrefix ipp : prefixes) {
                mPrefixes.put(ipp, MAX_URGENT_RTR_ADVERTISEMENTS);
            }
        }

        void removePrefixes(Set<IpPrefix> prefixes) {
            for (IpPrefix ipp : prefixes) {
                mPrefixes.remove(ipp);
            }
        }

        Set<Inet6Address> getDnses() { return mDnses.keySet(); }

        void putDnses(Set<Inet6Address> dnses) {
            for (Inet6Address dns : dnses) {
                mDnses.put(dns, MAX_URGENT_RTR_ADVERTISEMENTS);
            }
        }

        void removeDnses(Set<Inet6Address> dnses) {
            for (Inet6Address dns : dnses) {
                mDnses.remove(dns);
            }
        }

        boolean isEmpty() { return mPrefixes.isEmpty() && mDnses.isEmpty(); }

        private boolean decrementCounters() {
            boolean removed = decrementCounter(mPrefixes);
            removed |= decrementCounter(mDnses);
            return removed;
        }

        private <T> boolean decrementCounter(HashMap<T, Integer> map) {
            boolean removed = false;

            for (Iterator<Map.Entry<T, Integer>> it = map.entrySet().iterator();
                 it.hasNext();) {
                Map.Entry<T, Integer> kv = it.next();
                if (kv.getValue() == 0) {
                    it.remove();
                    removed = true;
                } else {
                    kv.setValue(kv.getValue() - 1);
                }
            }

            return removed;
        }
    }


    public RouterAdvertisementDaemon(InterfaceParams ifParams) {
        mInterface = ifParams;
        mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mInterface.index), 0);
        mDeprecatedInfoTracker = new DeprecatedInfoTracker();
    }

    public void buildNewRa(RaParams deprecatedParams, RaParams newParams) {
        synchronized (mLock) {
            if (deprecatedParams != null) {
                mDeprecatedInfoTracker.putPrefixes(deprecatedParams.prefixes);
                mDeprecatedInfoTracker.putDnses(deprecatedParams.dnses);
            }

            if (newParams != null) {
                // Process information that is no longer deprecated.
                mDeprecatedInfoTracker.removePrefixes(newParams.prefixes);
                mDeprecatedInfoTracker.removeDnses(newParams.dnses);
            }

            mRaParams = newParams;
            assembleRaLocked();
        }

        maybeNotifyMulticastTransmitter();
    }

    public boolean start() {
        if (!createSocket()) {
            return false;
        }

        mMulticastTransmitter = new MulticastTransmitter();
        mMulticastTransmitter.start();

        mUnicastResponder = new UnicastResponder();
        mUnicastResponder.start();

        return true;
    }

    public void stop() {
        closeSocket();
        // Wake up mMulticastTransmitter thread to interrupt a potential 1 day sleep before
        // the thread's termination.
        maybeNotifyMulticastTransmitter();
        mMulticastTransmitter = null;
        mUnicastResponder = null;
    }

    @GuardedBy("mLock")
    private void assembleRaLocked() {
        final ByteBuffer ra = ByteBuffer.wrap(mRA);
        ra.order(ByteOrder.BIG_ENDIAN);

        final boolean haveRaParams = (mRaParams != null);
        boolean shouldSendRA = false;

        try {
            putHeader(ra, haveRaParams && mRaParams.hasDefaultRoute,
                    haveRaParams ? mRaParams.hopLimit : RaParams.DEFAULT_HOPLIMIT);
            putSlla(ra, mInterface.macAddr.toByteArray());
            mRaLength = ra.position();

            // https://tools.ietf.org/html/rfc5175#section-4 says:
            //
            //     "MUST NOT be added to a Router Advertisement message
            //      if no flags in the option are set."
            //
            // putExpandedFlagsOption(ra);

            if (haveRaParams) {
                putMtu(ra, mRaParams.mtu);
                mRaLength = ra.position();

                for (IpPrefix ipp : mRaParams.prefixes) {
                    putPio(ra, ipp, DEFAULT_LIFETIME, DEFAULT_LIFETIME);
                    mRaLength = ra.position();
                    shouldSendRA = true;
                }

                if (mRaParams.dnses.size() > 0) {
                    putRdnss(ra, mRaParams.dnses, DEFAULT_LIFETIME);
                    mRaLength = ra.position();
                    shouldSendRA = true;
                }
            }

            for (IpPrefix ipp : mDeprecatedInfoTracker.getPrefixes()) {
                putPio(ra, ipp, 0, 0);
                mRaLength = ra.position();
                shouldSendRA = true;
            }

            final Set<Inet6Address> deprecatedDnses = mDeprecatedInfoTracker.getDnses();
            if (!deprecatedDnses.isEmpty()) {
                putRdnss(ra, deprecatedDnses, 0);
                mRaLength = ra.position();
                shouldSendRA = true;
            }
        } catch (BufferOverflowException e) {
            // The packet up to mRaLength  is valid, since it has been updated
            // progressively as the RA was built. Log an error, and continue
            // on as best as possible.
            Log.e(TAG, "Could not construct new RA: " + e);
        }

        // We have nothing worth announcing; indicate as much to maybeSendRA().
        if (!shouldSendRA) {
            mRaLength = 0;
        }
    }

    private void maybeNotifyMulticastTransmitter() {
        final MulticastTransmitter m = mMulticastTransmitter;
        if (m != null) {
            m.hup();
        }
    }

    private static Inet6Address getAllNodesForScopeId(int scopeId) {
        try {
            return Inet6Address.getByAddress("ff02::1", ALL_NODES, scopeId);
        } catch (UnknownHostException uhe) {
            Log.wtf(TAG, "Failed to construct ff02::1 InetAddress: " + uhe);
            return null;
        }
    }

    private static byte asByte(int value) { return (byte) value; }
    private static short asShort(int value) { return (short) value; }

    private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute, byte hopLimit) {
        /**
            Router Advertisement Message Format

             0                   1                   2                   3
             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
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |     Type      |     Code      |          Checksum             |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            | Cur Hop Limit |M|O|H|Prf|P|R|R|       Router Lifetime         |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                         Reachable Time                        |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                          Retrans Timer                        |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |   Options ...
            +-+-+-+-+-+-+-+-+-+-+-+-
        */
        ra.put(ICMPV6_ND_ROUTER_ADVERT)
          .put(asByte(0))
          .putShort(asShort(0))
          .put(hopLimit)
          // RFC 4191 "high" preference, iff. advertising a default route.
          .put(hasDefaultRoute ? asByte(0x08) : asByte(0))
          .putShort(hasDefaultRoute ? asShort(DEFAULT_LIFETIME) : asShort(0))
          .putInt(0)
          .putInt(0);
    }

    private static void putSlla(ByteBuffer ra, byte[] slla) {
        /**
            Source/Target Link-layer Address

             0                   1                   2                   3
             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
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |     Type      |    Length     |    Link-Layer Address ...
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        */
        if (slla == null || slla.length != 6) {
            // Only IEEE 802.3 6-byte addresses are supported.
            return;
        }
        final byte ND_OPTION_SLLA = 1;
        final byte SLLA_NUM_8OCTETS = 1;
        ra.put(ND_OPTION_SLLA)
          .put(SLLA_NUM_8OCTETS)
          .put(slla);
    }

    private static void putExpandedFlagsOption(ByteBuffer ra) {
        /**
            Router Advertisement Expanded Flags Option

             0                   1                   2                   3
             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
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |     Type      |    Length     |         Bit fields available ..
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            ... for assignment                                              |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */

        final byte ND_OPTION_EFO = 26;
        final byte EFO_NUM_8OCTETS = 1;

        ra.put(ND_OPTION_EFO)
          .put(EFO_NUM_8OCTETS)
          .putShort(asShort(0))
          .putInt(0);
    }

    private static void putMtu(ByteBuffer ra, int mtu) {
        /**
            MTU

             0                   1                   2                   3
             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
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |     Type      |    Length     |           Reserved            |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                              MTU                              |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        */
        final byte ND_OPTION_MTU = 5;
        final byte MTU_NUM_8OCTETS = 1;
        ra.put(ND_OPTION_MTU)
          .put(MTU_NUM_8OCTETS)
          .putShort(asShort(0))
          .putInt((mtu < IPV6_MIN_MTU) ? IPV6_MIN_MTU : mtu);
    }

    private static void putPio(ByteBuffer ra, IpPrefix ipp,
                               int validTime, int preferredTime) {
        /**
            Prefix Information

             0                   1                   2                   3
             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
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |     Type      |    Length     | Prefix Length |L|A| Reserved1 |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                         Valid Lifetime                        |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                       Preferred Lifetime                      |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                           Reserved2                           |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                                                               |
            +                                                               +
            |                                                               |
            +                            Prefix                             +
            |                                                               |
            +                                                               +
            |                                                               |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        */
        final int prefixLength = ipp.getPrefixLength();
        if (prefixLength != 64) {
            return;
        }
        final byte ND_OPTION_PIO = 3;
        final byte PIO_NUM_8OCTETS = 4;

        if (validTime < 0) validTime = 0;
        if (preferredTime < 0) preferredTime = 0;
        if (preferredTime > validTime) preferredTime = validTime;

        final byte[] addr = ipp.getAddress().getAddress();
        ra.put(ND_OPTION_PIO)
          .put(PIO_NUM_8OCTETS)
          .put(asByte(prefixLength))
          .put(asByte(0xc0)) /* L & A set */
          .putInt(validTime)
          .putInt(preferredTime)
          .putInt(0)
          .put(addr);
    }

    private static void putRio(ByteBuffer ra, IpPrefix ipp) {
        /**
            Route Information Option

             0                   1                   2                   3
             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
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |     Type      |    Length     | Prefix Length |Resvd|Prf|Resvd|
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                        Route Lifetime                         |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                   Prefix (Variable Length)                    |
            .                                                               .
            .                                                               .
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */
        final int prefixLength = ipp.getPrefixLength();
        if (prefixLength > 64) {
            return;
        }
        final byte ND_OPTION_RIO = 24;
        final byte RIO_NUM_8OCTETS = asByte(
                (prefixLength == 0) ? 1 : (prefixLength <= 8) ? 2 : 3);

        final byte[] addr = ipp.getAddress().getAddress();
        ra.put(ND_OPTION_RIO)
          .put(RIO_NUM_8OCTETS)
          .put(asByte(prefixLength))
          .put(asByte(0x18))
          .putInt(DEFAULT_LIFETIME);

        // Rely upon an IpPrefix's address being properly zeroed.
        if (prefixLength > 0) {
            ra.put(addr, 0, (prefixLength <= 64) ? 8 : 16);
        }
    }

    private static void putRdnss(ByteBuffer ra, Set<Inet6Address> dnses, int lifetime) {
        /**
            Recursive DNS Server (RDNSS) Option

             0                   1                   2                   3
             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
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |     Type      |     Length    |           Reserved            |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                           Lifetime                            |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |                                                               |
            :            Addresses of IPv6 Recursive DNS Servers            :
            |                                                               |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */

        final HashSet<Inet6Address> filteredDnses = new HashSet<>();
        for (Inet6Address dns : dnses) {
            if ((new LinkAddress(dns, RFC7421_PREFIX_LENGTH)).isGlobalPreferred()) {
                filteredDnses.add(dns);
            }
        }
        if (filteredDnses.isEmpty()) return;

        final byte ND_OPTION_RDNSS = 25;
        final byte RDNSS_NUM_8OCTETS = asByte(dnses.size() * 2 + 1);
        ra.put(ND_OPTION_RDNSS)
          .put(RDNSS_NUM_8OCTETS)
          .putShort(asShort(0))
          .putInt(lifetime);

        for (Inet6Address dns : filteredDnses) {
            // NOTE: If the full of list DNS servers doesn't fit in the packet,
            // this code will cause a buffer overflow and the RA won't include
            // this instance of the option at all.
            //
            // TODO: Consider looking at ra.remaining() to determine how many
            // DNS servers will fit, and adding only those.
            ra.put(dns.getAddress());
        }
    }

    private boolean createSocket() {
        final int SEND_TIMEOUT_MS = 300;

        final int oldTag = TrafficStats.getAndSetThreadStatsTag(
                TrafficStatsConstants.TAG_SYSTEM_NEIGHBOR);
        try {
            mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
            // Setting SNDTIMEO is purely for defensive purposes.
            Os.setsockoptTimeval(
                    mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
            Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
            NetworkUtils.protectFromVpn(mSocket);
            NetworkUtils.setupRaSocket(mSocket, mInterface.index);
        } catch (ErrnoException | IOException e) {
            Log.e(TAG, "Failed to create RA daemon socket: " + e);
            return false;
        } finally {
            TrafficStats.setThreadStatsTag(oldTag);
        }

        return true;
    }

    private void closeSocket() {
        if (mSocket != null) {
            try {
                IoBridge.closeAndSignalBlockedThreads(mSocket);
            } catch (IOException ignored) {}
        }
        mSocket = null;
    }

    private boolean isSocketValid() {
        final FileDescriptor s = mSocket;
        return (s != null) && s.valid();
    }

    private boolean isSuitableDestination(InetSocketAddress dest) {
        if (mAllNodes.equals(dest)) {
            return true;
        }

        final InetAddress destip = dest.getAddress();
        return (destip instanceof Inet6Address) &&
                destip.isLinkLocalAddress() &&
               (((Inet6Address) destip).getScopeId() == mInterface.index);
    }

    private void maybeSendRA(InetSocketAddress dest) {
        if (dest == null || !isSuitableDestination(dest)) {
            dest = mAllNodes;
        }

        try {
            synchronized (mLock) {
                if (mRaLength < MIN_RA_HEADER_SIZE) {
                    // No actual RA to send.
                    return;
                }
                Os.sendto(mSocket, mRA, 0, mRaLength, 0, dest);
            }
            Log.d(TAG, "RA sendto " + dest.getAddress().getHostAddress());
        } catch (ErrnoException | SocketException e) {
            if (isSocketValid()) {
                Log.e(TAG, "sendto error: " + e);
            }
        }
    }

    private final class UnicastResponder extends Thread {
        private final InetSocketAddress solicitor = new InetSocketAddress();
        // The recycled buffer for receiving Router Solicitations from clients.
        // If the RS is larger than IPV6_MIN_MTU the packets are truncated.
        // This is fine since currently only byte 0 is examined anyway.
        private final byte mSolication[] = new byte[IPV6_MIN_MTU];

        @Override
        public void run() {
            while (isSocketValid()) {
                try {
                    // Blocking receive.
                    final int rval = Os.recvfrom(
                            mSocket, mSolication, 0, mSolication.length, 0, solicitor);
                    // Do the least possible amount of validation.
                    if (rval < 1 || mSolication[0] != ICMPV6_ND_ROUTER_SOLICIT) {
                        continue;
                    }
                } catch (ErrnoException | SocketException e) {
                    if (isSocketValid()) {
                        Log.e(TAG, "recvfrom error: " + e);
                    }
                    continue;
                }

                maybeSendRA(solicitor);
            }
        }
    }

    // TODO: Consider moving this to run on a provided Looper as a Handler,
    // with WakeupMessage-style messages providing the timer driven input.
    private final class MulticastTransmitter extends Thread {
        private final Random mRandom = new Random();
        private final AtomicInteger mUrgentAnnouncements = new AtomicInteger(0);

        @Override
        public void run() {
            while (isSocketValid()) {
                try {
                    Thread.sleep(getNextMulticastTransmitDelayMs());
                } catch (InterruptedException ignored) {
                    // Stop sleeping, immediately send an RA, and continue.
                }

                maybeSendRA(mAllNodes);
                synchronized (mLock) {
                    if (mDeprecatedInfoTracker.decrementCounters()) {
                        // At least one deprecated PIO has been removed;
                        // reassemble the RA.
                        assembleRaLocked();
                    }
                }
            }
        }

        public void hup() {
            // Set to one fewer that the desired number, because as soon as
            // the thread interrupt is processed we immediately send an RA
            // and mUrgentAnnouncements is not examined until the subsequent
            // sleep interval computation (i.e. this way we send 3 and not 4).
            mUrgentAnnouncements.set(MAX_URGENT_RTR_ADVERTISEMENTS - 1);
            interrupt();
        }

        private int getNextMulticastTransmitDelaySec() {
            boolean deprecationInProgress = false;
            synchronized (mLock) {
                if (mRaLength < MIN_RA_HEADER_SIZE) {
                    // No actual RA to send; just sleep for 1 day.
                    return DAY_IN_SECONDS;
                }
                deprecationInProgress = !mDeprecatedInfoTracker.isEmpty();
            }

            final int urgentPending = mUrgentAnnouncements.getAndDecrement();
            if ((urgentPending > 0) || deprecationInProgress) {
                return MIN_DELAY_BETWEEN_RAS_SEC;
            }

            return MIN_RTR_ADV_INTERVAL_SEC + mRandom.nextInt(
                    MAX_RTR_ADV_INTERVAL_SEC - MIN_RTR_ADV_INTERVAL_SEC);
        }

        private long getNextMulticastTransmitDelayMs() {
            return 1000 * (long) getNextMulticastTransmitDelaySec();
        }
    }
}
