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