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