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 com.android.server.wifi.aware; 18 19 import static android.net.RouteInfo.RTN_UNICAST; 20 21 import android.content.Context; 22 import android.hardware.wifi.V1_0.NanDataPathChannelCfg; 23 import android.hardware.wifi.V1_0.NanStatusType; 24 import android.hardware.wifi.V1_2.NanDataPathChannelInfo; 25 import android.net.ConnectivityManager; 26 import android.net.IpPrefix; 27 import android.net.LinkAddress; 28 import android.net.LinkProperties; 29 import android.net.MacAddress; 30 import android.net.MatchAllNetworkSpecifier; 31 import android.net.NetworkAgent; 32 import android.net.NetworkAgentConfig; 33 import android.net.NetworkCapabilities; 34 import android.net.NetworkFactory; 35 import android.net.NetworkProvider; 36 import android.net.NetworkRequest; 37 import android.net.NetworkSpecifier; 38 import android.net.RouteInfo; 39 import android.net.wifi.aware.TlvBufferUtils; 40 import android.net.wifi.aware.WifiAwareAgentNetworkSpecifier; 41 import android.net.wifi.aware.WifiAwareManager; 42 import android.net.wifi.aware.WifiAwareNetworkInfo; 43 import android.net.wifi.aware.WifiAwareNetworkSpecifier; 44 import android.net.wifi.aware.WifiAwareUtils; 45 import android.net.wifi.util.HexEncoding; 46 import android.os.Build; 47 import android.os.Handler; 48 import android.os.Looper; 49 import android.text.TextUtils; 50 import android.util.ArrayMap; 51 import android.util.Log; 52 import android.util.Pair; 53 import android.util.SparseArray; 54 55 import com.android.internal.annotations.VisibleForTesting; 56 import com.android.modules.utils.build.SdkLevel; 57 import com.android.server.wifi.Clock; 58 import com.android.server.wifi.util.NetdWrapper; 59 import com.android.server.wifi.util.WifiPermissionsUtil; 60 import com.android.server.wifi.util.WifiPermissionsWrapper; 61 import com.android.wifi.resources.R; 62 63 import java.io.FileDescriptor; 64 import java.io.PrintWriter; 65 import java.net.DatagramSocket; 66 import java.net.Inet6Address; 67 import java.net.InetAddress; 68 import java.net.NetworkInterface; 69 import java.net.SocketException; 70 import java.net.UnknownHostException; 71 import java.nio.ByteOrder; 72 import java.util.Arrays; 73 import java.util.Enumeration; 74 import java.util.HashSet; 75 import java.util.Iterator; 76 import java.util.List; 77 import java.util.Map; 78 import java.util.Set; 79 import java.util.SortedSet; 80 import java.util.TreeSet; 81 82 /** 83 * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down. 84 * The Aware network configuration is: 85 * - transport = TRANSPORT_WIFI_AWARE 86 * - capabilities = NET_CAPABILITY_NOT_VPN 87 * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or 88 * WifiAwareManager.createNetworkSpecifier(...). 89 */ 90 public class WifiAwareDataPathStateManager { 91 private static final String TAG = "WifiAwareDataPathStMgr"; 92 private static final boolean VDBG = false; // STOPSHIP if true 93 private boolean mDbg = false; 94 95 private static final String AWARE_INTERFACE_PREFIX = "aware_data"; 96 private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY"; 97 private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_"; 98 private static final int NETWORK_FACTORY_SCORE_AVAIL = 1; 99 private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1; 100 private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1; 101 102 @VisibleForTesting 103 public static final int ADDRESS_VALIDATION_RETRY_INTERVAL_MS = 1_000; // 1 second 104 @VisibleForTesting 105 public static final int ADDRESS_VALIDATION_TIMEOUT_MS = 5_000; // 5 seconds 106 107 private final WifiAwareStateManager mMgr; 108 private final Clock mClock; 109 public NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper(); 110 private static final NetworkCapabilities sNetworkCapabilitiesFilter = 111 makeNetworkCapabilitiesFilter(); 112 private final Set<String> mInterfaces = new HashSet<>(); 113 private final ArrayMap<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> 114 mNetworkRequestsCache = new ArrayMap<>(); 115 private Context mContext; 116 private WifiAwareMetrics mAwareMetrics; 117 private WifiPermissionsUtil mWifiPermissionsUtil; 118 private WifiPermissionsWrapper mPermissionsWrapper; 119 private Looper mLooper; 120 private Handler mHandler; 121 private WifiAwareNetworkFactory mNetworkFactory; 122 public NetdWrapper mNetdWrapper; 123 124 // internal debug flag to override API check 125 /* package */ boolean mAllowNdpResponderFromAnyOverride = false; 126 WifiAwareDataPathStateManager(WifiAwareStateManager mgr, Clock clock)127 public WifiAwareDataPathStateManager(WifiAwareStateManager mgr, Clock clock) { 128 mMgr = mgr; 129 mClock = clock; 130 } 131 makeNetworkCapabilitiesFilter()132 private static NetworkCapabilities makeNetworkCapabilitiesFilter() { 133 NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder() 134 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) 135 .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 136 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 137 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) 138 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) 139 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) 140 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 141 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 142 .setNetworkSpecifier(new MatchAllNetworkSpecifier()) 143 .setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL) 144 .setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL) 145 .setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL); 146 if (SdkLevel.isAtLeastS()) { 147 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); 148 } 149 return builder.build(); 150 } 151 152 /** 153 * Initialize the Aware data-path state manager. Specifically register the network factory with 154 * connectivity service. 155 */ start(Context context, Looper looper, WifiAwareMetrics awareMetrics, WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, NetdWrapper netdWrapper)156 public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics, 157 WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, 158 NetdWrapper netdWrapper) { 159 if (VDBG) Log.v(TAG, "start"); 160 161 mContext = context; 162 mAwareMetrics = awareMetrics; 163 mWifiPermissionsUtil = wifiPermissionsUtil; 164 mPermissionsWrapper = permissionsWrapper; 165 mNetdWrapper = netdWrapper; 166 mLooper = looper; 167 mHandler = new Handler(mLooper); 168 169 170 mNetworkFactory = new WifiAwareNetworkFactory(looper, context, sNetworkCapabilitiesFilter); 171 mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL); 172 mNetworkFactory.register(); 173 } 174 175 /** 176 * Enable verbose logging. 177 */ enableVerboseLogging(boolean verbose)178 public void enableVerboseLogging(boolean verbose) { 179 mDbg = verbose | VDBG; 180 } 181 182 /** 183 * Get the number of the NDPs is already set up. 184 */ getNumOfNdps()185 public int getNumOfNdps() { 186 int numOfNdps = 0; 187 for (AwareNetworkRequestInformation requestInformation : mNetworkRequestsCache.values()) { 188 numOfNdps += requestInformation.ndpInfos.size(); 189 } 190 return numOfNdps; 191 } 192 193 private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> getNetworkRequestByNdpId(int ndpId)194 getNetworkRequestByNdpId(int ndpId) { 195 for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : 196 mNetworkRequestsCache.entrySet()) { 197 if (entry.getValue().ndpInfos.contains(ndpId)) { 198 return entry; 199 } 200 } 201 202 return null; 203 } 204 205 private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci)206 getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci) { 207 if (VDBG) Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: cci=" + cci); 208 for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : 209 mNetworkRequestsCache.entrySet()) { 210 if (VDBG) { 211 Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: entry=" + entry.getValue() 212 + " --> cci=" + entry.getValue().getCanonicalDescriptor()); 213 } 214 if (entry.getValue().getCanonicalDescriptor().matches(cci)) { 215 return entry; 216 } 217 } 218 219 return null; 220 } 221 222 /** 223 * Create all Aware data-path interfaces which are possible on the device - based on the 224 * capabilities of the firmware. 225 */ createAllInterfaces()226 public void createAllInterfaces() { 227 if (mDbg) Log.v(TAG, "createAllInterfaces"); 228 229 if (mMgr.getCapabilities() == null) { 230 Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!"); 231 return; 232 } 233 234 for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) { 235 String name = AWARE_INTERFACE_PREFIX + i; 236 if (mInterfaces.contains(name)) { 237 Log.e(TAG, "createAllInterfaces(): interface already up, " + name 238 + ", possibly failed to delete - deleting/creating again to be safe"); 239 mMgr.deleteDataPathInterface(name); 240 241 // critical to remove so that don't get infinite loop if the delete fails again 242 mInterfaces.remove(name); 243 } 244 245 mMgr.createDataPathInterface(name); 246 } 247 } 248 249 /** 250 * Delete all Aware data-path interfaces which are currently up. 251 */ deleteAllInterfaces()252 public void deleteAllInterfaces() { 253 if (mDbg) Log.v(TAG, "deleteAllInterfaces"); 254 onAwareDownCleanupDataPaths(); 255 256 if (mMgr.getCapabilities() == null) { 257 Log.e(TAG, "deleteAllInterfaces: capabilities aren't initialized yet!"); 258 return; 259 } 260 261 for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) { 262 String name = AWARE_INTERFACE_PREFIX + i; 263 mMgr.deleteDataPathInterface(name); 264 } 265 } 266 267 /** 268 * Called when firmware indicates the an interface was created. 269 */ onInterfaceCreated(String interfaceName)270 public void onInterfaceCreated(String interfaceName) { 271 if (mDbg) Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName); 272 273 if (mInterfaces.contains(interfaceName)) { 274 Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName); 275 } 276 277 mInterfaces.add(interfaceName); 278 } 279 280 /** 281 * Called when firmware indicates the an interface was deleted. 282 */ onInterfaceDeleted(String interfaceName)283 public void onInterfaceDeleted(String interfaceName) { 284 if (mDbg) Log.v(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName); 285 286 if (!mInterfaces.contains(interfaceName)) { 287 Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName); 288 } 289 290 mInterfaces.remove(interfaceName); 291 } 292 293 /** 294 * Response to initiating data-path request. Indicates that request is successful (not 295 * complete!) and is now in progress. 296 * 297 * @param networkSpecifier The network specifier provided as part of the initiate request. 298 * @param ndpId The ID assigned to the data-path. 299 * @return False if has error, otherwise return true 300 */ onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier, int ndpId)301 public boolean onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier, 302 int ndpId) { 303 if (mDbg) { 304 Log.v(TAG, 305 "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId=" 306 + ndpId); 307 } 308 309 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 310 if (nnri == null) { 311 Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier=" 312 + networkSpecifier); 313 mMgr.endDataPath(ndpId); 314 return false; 315 } 316 317 if (nnri.state 318 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { 319 Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state=" 320 + nnri.state); 321 mMgr.endDataPath(ndpId); 322 mNetworkRequestsCache.remove(networkSpecifier); 323 declareUnfullfillable(nnri); 324 return false; 325 } 326 327 NdpInfo ndpInfo = new NdpInfo(ndpId); 328 ndpInfo.state = NdpInfo.STATE_WAIT_FOR_CONFIRM; 329 ndpInfo.peerDiscoveryMac = nnri.specifiedPeerDiscoveryMac; 330 nnri.ndpInfos.put(ndpId, ndpInfo); 331 332 nnri.state = AwareNetworkRequestInformation.STATE_IN_SETUP; 333 334 return true; 335 } 336 337 /** 338 * Response to an attempt to set up a data-path (on the initiator side). 339 * 340 * @param networkSpecifier The network specifier provided as part of the initiate request. 341 * @param reason Failure reason. 342 */ onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason)343 public void onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason) { 344 if (mDbg) { 345 Log.v(TAG, 346 "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason=" 347 + reason); 348 } 349 350 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier); 351 if (nnri == null) { 352 Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier=" 353 + networkSpecifier); 354 return; 355 } 356 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 357 358 if (nnri.state 359 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { 360 Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state=" 361 + nnri.state); 362 } 363 364 mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), 365 mClock.getElapsedSinceBootMillis()); 366 } 367 368 369 /** 370 * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path 371 * connection with us. 372 * 373 * @param pubSubId The ID of the discovery session context for the data-path - or 0 if not 374 * related to a discovery session. 375 * @param mac The discovery MAC address of the peer. 376 * @param ndpId The locally assigned ID for the data-path. 377 * @param message The app_info HAL field (peer's info: binary blob) 378 * @return False if has error, otherwise return true 379 */ onDataPathRequest(int pubSubId, byte[] mac, int ndpId, byte[] message)380 public boolean onDataPathRequest(int pubSubId, byte[] mac, int ndpId, 381 byte[] message) { 382 if (mDbg) { 383 Log.v(TAG, 384 "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf( 385 HexEncoding.encode(mac)) + ", ndpId=" + ndpId); 386 } 387 388 // it is also possible that this is an initiator-side data-path request indication (which 389 // happens when the Responder responds). In such a case it will be matched by the NDP ID. 390 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 391 getNetworkRequestByNdpId(ndpId); 392 if (nnriE != null) { 393 if (VDBG) { 394 Log.v(TAG, 395 "onDataPathRequest: initiator-side indication for " + nnriE); 396 } 397 NdpInfo ndpInfo = nnriE.getValue().ndpInfos.get(ndpId); 398 // potential transmission mechanism for port/transport-protocol information from 399 // Responder (alternative to confirm message) 400 NetworkInformationData.ParsedResults peerServerInfo = NetworkInformationData.parseTlv( 401 message); 402 if (ndpInfo == null) { 403 Log.wtf(TAG, "onDataPathRequest: initiator-side ndpInfo is null?!"); 404 return false; 405 } 406 if (peerServerInfo != null) { 407 if (peerServerInfo.port != 0) { 408 ndpInfo.peerPort = peerServerInfo.port; 409 } 410 if (peerServerInfo.transportProtocol != -1) { 411 ndpInfo.peerTransportProtocol = peerServerInfo.transportProtocol; 412 } 413 if (peerServerInfo.ipv6Override != null) { 414 ndpInfo.peerIpv6Override = peerServerInfo.ipv6Override; 415 } 416 } 417 418 return false; //ignore this for NDP set up flow: it is used to obtain app_info from Resp 419 } 420 421 AwareNetworkRequestInformation nnri = null; 422 WifiAwareNetworkSpecifier networkSpecifier = null; 423 for (int i = 0; i < mNetworkRequestsCache.size(); i++) { 424 AwareNetworkRequestInformation requestInfo = mNetworkRequestsCache.valueAt(i); 425 /* 426 * Checking that the incoming request (from the Initiator) matches the request 427 * we (the Responder) already have set up. The rules are: 428 * - The discovery session (pub/sub ID) must match. 429 * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC == 430 * accept (otherwise matching) requests from any peer MAC. 431 * - The request must be pending (i.e. we could have completed requests for the same 432 * parameters) 433 */ 434 if (requestInfo.pubSubId != 0 && requestInfo.pubSubId != pubSubId) { 435 continue; 436 } 437 438 if (requestInfo.specifiedPeerDiscoveryMac != null) { 439 if (Arrays.equals(requestInfo.specifiedPeerDiscoveryMac, mac) && requestInfo.state 440 == AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) { 441 // If a peer specific request matches, use it. 442 networkSpecifier = mNetworkRequestsCache.keyAt(i); 443 nnri = requestInfo; 444 break; 445 } 446 continue; 447 } 448 // For Accept any, multiple NDP may setup in the same time. In idle or terminating state 449 // it will not accept any request. 450 if (requestInfo.state != AwareNetworkRequestInformation.STATE_IDLE 451 && requestInfo.state != AwareNetworkRequestInformation.STATE_TERMINATING) { 452 // If an accepts any request matches, continually find if there is a peer specific 453 // one. If there isn't any matched peer specific one, use the accepts any peer 454 // request. 455 networkSpecifier = mNetworkRequestsCache.keyAt(i); 456 nnri = requestInfo; 457 } 458 } 459 460 if (nnri == null) { 461 Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId 462 + ", mac=" + String.valueOf(HexEncoding.encode(mac))); 463 if (VDBG) { 464 Log.v(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache); 465 } 466 mMgr.respondToDataPathRequest(false, ndpId, "", null, null, null, false); 467 return false; 468 } 469 470 if (nnri.interfaceName == null) { 471 nnri.interfaceName = selectInterfaceForRequest(nnri); 472 } 473 if (nnri.interfaceName == null) { 474 Log.w(TAG, 475 "onDataPathRequest: request " + networkSpecifier + " no interface available"); 476 mMgr.respondToDataPathRequest(false, ndpId, "", null, null, null, false); 477 mNetworkRequestsCache.remove(networkSpecifier); 478 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 479 return false; 480 } 481 482 NdpInfo ndpInfo = new NdpInfo(ndpId); 483 ndpInfo.state = NdpInfo.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE; 484 ndpInfo.peerDiscoveryMac = mac; 485 ndpInfo.startTimestamp = mClock.getElapsedSinceBootMillis(); 486 nnri.ndpInfos.put(ndpId, ndpInfo); 487 488 nnri.state = AwareNetworkRequestInformation.STATE_IN_SETUP; 489 mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.networkSpecifier.pmk, 490 nnri.networkSpecifier.passphrase, 491 NetworkInformationData.buildTlv(nnri.networkSpecifier.port, 492 nnri.networkSpecifier.transportProtocol), 493 nnri.networkSpecifier.isOutOfBand()); 494 495 return true; 496 } 497 498 /** 499 * Called on the RESPONDER when the response to data-path request has been completed. 500 * 501 * @param ndpId The ID of the data-path (NDP) 502 * @param success Whether or not the 'RespondToDataPathRequest' operation was a success. 503 */ onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure)504 public void onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure) { 505 if (mDbg) { 506 Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success); 507 } 508 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 509 getNetworkRequestByNdpId(ndpId); 510 511 if (nnriE == null) { 512 Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId=" 513 + ndpId); 514 if (VDBG) { 515 Log.v(TAG, "onRespondToDataPathRequest: network request cache = " 516 + mNetworkRequestsCache); 517 } 518 return; 519 } 520 521 WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey(); 522 AwareNetworkRequestInformation nnri = nnriE.getValue(); 523 NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId); 524 if (!success) { 525 Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier 526 + " failed responding"); 527 mMgr.endDataPath(ndpId); 528 nnri.ndpInfos.remove(ndpId); 529 if (nnri.specifiedPeerDiscoveryMac != null) { 530 mNetworkRequestsCache.remove(networkSpecifier); 531 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 532 } 533 mAwareMetrics.recordNdpStatus(reasonOnFailure, networkSpecifier.isOutOfBand(), 534 ndpInfo.startTimestamp); 535 return; 536 } 537 538 if (ndpInfo.state != NdpInfo.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE 539 || nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) { 540 Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier 541 + " is incorrect state=" + nnri.state); 542 mMgr.endDataPath(ndpId); 543 nnri.ndpInfos.remove(ndpId); 544 if (nnri.specifiedPeerDiscoveryMac != null) { 545 mNetworkRequestsCache.remove(networkSpecifier); 546 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 547 } 548 return; 549 } 550 551 ndpInfo.state = NdpInfo.STATE_WAIT_FOR_CONFIRM; 552 } 553 554 /** 555 * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up) 556 * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's 557 * perspective - now can do L3 configuration. 558 * 559 * @param ndpId Id of the data-path 560 * @param mac The MAC address of the peer's data-path (not discovery interface). Only 561 * valid 562 * if {@code accept} is {@code true}. 563 * @param accept Indicates whether the data-path setup has succeeded (been accepted) or 564 * failed (been rejected). 565 * @param reason If {@code accept} is {@code false} provides a reason code for the 566 * rejection/failure. 567 * @param message The message provided by the peer as part of the data-path setup 568 * process. 569 * @param channelInfo Lists of channels used for this NDP. 570 * @return False if has error, otherwise return true 571 */ onDataPathConfirm(int ndpId, byte[] mac, boolean accept, int reason, byte[] message, List<NanDataPathChannelInfo> channelInfo)572 public boolean onDataPathConfirm(int ndpId, byte[] mac, boolean accept, 573 int reason, byte[] message, List<NanDataPathChannelInfo> channelInfo) { 574 if (mDbg) { 575 Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId + ", mac=" + String.valueOf( 576 HexEncoding.encode(mac)) + ", accept=" + accept + ", reason=" + reason 577 + ", message.length=" + ((message == null) ? 0 : message.length) 578 + ", channelInfo=" + channelInfo); 579 } 580 581 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 582 getNetworkRequestByNdpId(ndpId); 583 if (nnriE == null) { 584 Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId); 585 if (accept) { 586 mMgr.endDataPath(ndpId); 587 } 588 return false; 589 } 590 591 WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey(); 592 AwareNetworkRequestInformation nnri = nnriE.getValue(); 593 NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId); 594 595 // validate state 596 if (ndpInfo.state != NdpInfo.STATE_WAIT_FOR_CONFIRM 597 || nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) { 598 Log.w(TAG, "onDataPathConfirm: invalid state=" + nnri.state); 599 nnri.ndpInfos.remove(ndpId); 600 if (nnri.specifiedPeerDiscoveryMac != null) { 601 mNetworkRequestsCache.remove(networkSpecifier); 602 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 603 } 604 if (accept) { 605 mMgr.endDataPath(ndpId); 606 } 607 return false; 608 } 609 610 if (accept) { 611 ndpInfo.peerDataMac = mac; 612 ndpInfo.state = NdpInfo.STATE_CONFIRMED; 613 ndpInfo.channelInfo = channelInfo; 614 nnri.state = AwareNetworkRequestInformation.STATE_CONFIRMED; 615 // NetworkAgent may already be created for accept any peer request, interface should be 616 // ready in that case. 617 if (nnri.networkAgent == null && !isInterfaceUpAndUsedByAnotherNdp(nnri)) { 618 try { 619 mNetdWrapper.setInterfaceUp(nnri.interfaceName); 620 mNetdWrapper.enableIpv6(nnri.interfaceName); 621 } catch (Exception e) { // NwService throws runtime exceptions for errors 622 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 623 + ": can't configure network - " 624 + e); 625 mMgr.endDataPath(ndpId); 626 if (nnri.specifiedPeerDiscoveryMac != null) { 627 declareUnfullfillable(nnri); 628 } 629 return true; 630 } 631 } else { 632 if (VDBG) { 633 Log.v(TAG, "onDataPathConfirm: interface already configured: " 634 + nnri.interfaceName); 635 } 636 } 637 638 // only relevant for the initiator 639 if (nnri.networkSpecifier.role 640 == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) { 641 NetworkInformationData.ParsedResults peerServerInfo = 642 NetworkInformationData.parseTlv(message); 643 if (peerServerInfo != null) { 644 if (peerServerInfo.port != 0) { 645 ndpInfo.peerPort = peerServerInfo.port; 646 } 647 if (peerServerInfo.transportProtocol != -1) { 648 ndpInfo.peerTransportProtocol = peerServerInfo.transportProtocol; 649 } 650 if (peerServerInfo.ipv6Override != null) { 651 ndpInfo.peerIpv6Override = peerServerInfo.ipv6Override; 652 } 653 } 654 } 655 656 nnri.startValidationTimestamp = mClock.getElapsedSinceBootMillis(); 657 handleAddressValidation(nnri, ndpInfo, networkSpecifier.isOutOfBand(), mac); 658 } else { 659 if (VDBG) { 660 Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier 661 + " rejected - reason=" + reason); 662 } 663 nnri.ndpInfos.remove(ndpId); 664 if (nnri.specifiedPeerDiscoveryMac != null) { 665 mNetworkRequestsCache.remove(networkSpecifier); 666 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 667 } 668 mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), 669 ndpInfo.startTimestamp); 670 } 671 return true; 672 } 673 getInet6Address(NdpInfo ndpInfo, byte[] mac, String interfaceName)674 private void getInet6Address(NdpInfo ndpInfo, byte[] mac, String interfaceName) { 675 try { 676 byte[] addr; 677 if (ndpInfo.peerIpv6Override == null) { 678 addr = MacAddress.fromBytes(mac).getLinkLocalIpv6FromEui48Mac().getAddress(); 679 } else { 680 addr = new byte[16]; 681 addr[0] = (byte) 0xfe; 682 addr[1] = (byte) 0x80; 683 addr[8] = ndpInfo.peerIpv6Override[0]; 684 addr[9] = ndpInfo.peerIpv6Override[1]; 685 addr[10] = ndpInfo.peerIpv6Override[2]; 686 addr[11] = ndpInfo.peerIpv6Override[3]; 687 addr[12] = ndpInfo.peerIpv6Override[4]; 688 addr[13] = ndpInfo.peerIpv6Override[5]; 689 addr[14] = ndpInfo.peerIpv6Override[6]; 690 addr[15] = ndpInfo.peerIpv6Override[7]; 691 } 692 ndpInfo.peerIpv6 = Inet6Address.getByAddress(null, addr, 693 NetworkInterface.getByName(interfaceName)); 694 } catch (SocketException | UnknownHostException e) { 695 if (mDbg) { 696 Log.d(TAG, "onDataPathConfirm: error obtaining scoped IPv6 address -- " + e); 697 } 698 ndpInfo.peerIpv6 = null; 699 } 700 } 701 handleAddressValidation(AwareNetworkRequestInformation nnri, NdpInfo ndpInfo, boolean isOutOfBand, byte[] mac)702 private void handleAddressValidation(AwareNetworkRequestInformation nnri, NdpInfo ndpInfo, 703 boolean isOutOfBand, byte[] mac) { 704 final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder( 705 sNetworkCapabilitiesFilter); 706 LinkProperties linkProperties = new LinkProperties(); 707 getInet6Address(ndpInfo, mac, nnri.interfaceName); 708 if (!(ndpInfo.peerIpv6 != null && mNiWrapper.configureAgentProperties(nnri, 709 ncBuilder, linkProperties) 710 && mNiWrapper.isAddressUsable(linkProperties))) { 711 if (VDBG) { 712 Log.d(TAG, "Failed address validation"); 713 } 714 if (!isAddressValidationExpired(nnri, ndpInfo.ndpId)) { 715 mHandler.postDelayed(() -> 716 handleAddressValidation(nnri, ndpInfo, isOutOfBand, mac), 717 ADDRESS_VALIDATION_RETRY_INTERVAL_MS); 718 } 719 return; 720 } 721 722 // Network agent may already setup finished. Update peer network info. 723 if (nnri.networkAgent == null) { 724 // Setup first NDP for new networkAgent. 725 final WifiAwareNetworkInfo ni = new WifiAwareNetworkInfo(ndpInfo.peerIpv6, 726 ndpInfo.peerPort, ndpInfo.peerTransportProtocol); 727 ncBuilder.setTransportInfo(ni); 728 if (VDBG) { 729 Log.v(TAG, "onDataPathConfirm: AwareNetworkInfo=" + ni); 730 } 731 final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder() 732 .setLegacyType(ConnectivityManager.TYPE_NONE) 733 .setLegacyTypeName(NETWORK_TAG) 734 .build(); 735 nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext, 736 AGENT_TAG_PREFIX + ndpInfo.ndpId, ncBuilder.build(), linkProperties, 737 NETWORK_FACTORY_SCORE_AVAIL, naConfig, mNetworkFactory.getProvider(), nnri); 738 mNiWrapper.setConnected(nnri.networkAgent); 739 } 740 mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, isOutOfBand, ndpInfo.startTimestamp); 741 mAwareMetrics.recordNdpCreation(nnri.uid, nnri.packageName, mNetworkRequestsCache); 742 } 743 isAddressValidationExpired(AwareNetworkRequestInformation nnri, int ndpId)744 private boolean isAddressValidationExpired(AwareNetworkRequestInformation nnri, int ndpId) { 745 if (mClock.getElapsedSinceBootMillis() - nnri.startValidationTimestamp 746 > ADDRESS_VALIDATION_TIMEOUT_MS) { 747 Log.e(TAG, "Timed-out while waiting for IPv6 address to be usable"); 748 mMgr.endDataPath(ndpId); 749 if (nnri.specifiedPeerDiscoveryMac != null) { 750 declareUnfullfillable(nnri); 751 } 752 return true; 753 } 754 return false; 755 } 756 declareUnfullfillable(AwareNetworkRequestInformation nnri)757 private void declareUnfullfillable(AwareNetworkRequestInformation nnri) { 758 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 759 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 760 } 761 762 /** 763 * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has 764 * been terminated. 765 * 766 * @param ndpId The ID of the terminated data-path. 767 */ onDataPathEnd(int ndpId)768 public void onDataPathEnd(int ndpId) { 769 if (mDbg) Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId); 770 771 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 772 getNetworkRequestByNdpId(ndpId); 773 if (nnriE == null) { 774 if (VDBG) { 775 Log.v(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId); 776 } 777 return; 778 } 779 AwareNetworkRequestInformation nnri = nnriE.getValue(); 780 NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId); 781 nnri.ndpInfos.remove(ndpId); 782 783 if (ndpInfo.state == NdpInfo.STATE_CONFIRMED) { 784 mAwareMetrics.recordNdpSessionDuration(ndpInfo.startTimestamp); 785 } 786 if (nnri.specifiedPeerDiscoveryMac == null 787 && nnri.state != AwareNetworkRequestInformation.STATE_TERMINATING) { 788 return; 789 } 790 if (nnri.ndpInfos.size() == 0) { 791 tearDownInterfaceIfPossible(nnri); 792 mNetworkRequestsCache.remove(nnriE.getKey()); 793 mNetworkFactory.tickleConnectivityIfWaiting(); 794 } 795 } 796 797 /** 798 * Notification (unsolicited/asynchronous) from the firmware that the channel for the specified 799 * NDP ids has been updated. 800 */ onDataPathSchedUpdate(byte[] peerMac, List<Integer> ndpIds, List<NanDataPathChannelInfo> channelInfo)801 public void onDataPathSchedUpdate(byte[] peerMac, List<Integer> ndpIds, 802 List<NanDataPathChannelInfo> channelInfo) { 803 if (mDbg) { 804 Log.v(TAG, "onDataPathSchedUpdate: peerMac=" + MacAddress.fromBytes(peerMac).toString() 805 + ", ndpIds=" + ndpIds + ", channelInfo=" + channelInfo); 806 } 807 808 for (int ndpId : ndpIds) { 809 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 810 getNetworkRequestByNdpId(ndpId); 811 if (nnriE == null) { 812 Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + " - not found"); 813 continue; 814 } 815 NdpInfo ndpInfo = nnriE.getValue().ndpInfos.get(ndpId); 816 if (!Arrays.equals(peerMac, ndpInfo.peerDiscoveryMac)) { 817 Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + ", report NMI=" 818 + MacAddress.fromBytes(peerMac).toString() + " doesn't match NDP NMI=" 819 + MacAddress.fromBytes(ndpInfo.peerDiscoveryMac).toString()); 820 continue; 821 } 822 823 ndpInfo.channelInfo = channelInfo; 824 } 825 } 826 827 /** 828 * Called whenever Aware comes down. Clean up all pending and up network requests and agents. 829 */ onAwareDownCleanupDataPaths()830 public void onAwareDownCleanupDataPaths() { 831 if (mDbg) Log.v(TAG, "onAwareDownCleanupDataPaths"); 832 833 Iterator<Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>> it = 834 mNetworkRequestsCache.entrySet().iterator(); 835 while (it.hasNext()) { 836 AwareNetworkRequestInformation nnri = it.next().getValue(); 837 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 838 tearDownInterfaceIfPossible(nnri); 839 it.remove(); 840 } 841 } 842 843 /** 844 * Called when timed-out waiting for confirmation of the data-path setup (i.e. 845 * onDataPathConfirm). Started on the initiator when executing the request for the data-path 846 * and on the responder when received a request for data-path (in both cases only on success 847 * - i.e. when we're proceeding with data-path setup). 848 */ handleDataPathTimeout(int ndpId)849 public void handleDataPathTimeout(int ndpId) { 850 if (mDbg) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + ndpId); 851 852 853 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 854 getNetworkRequestByNdpId(ndpId); 855 if (nnriE == null) { 856 if (VDBG) { 857 Log.v(TAG, 858 "handleDataPathTimeout: network request not found for networkSpecifier=" 859 + ndpId); 860 } 861 return; 862 } 863 AwareNetworkRequestInformation nnri = nnriE.getValue(); 864 NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId); 865 mAwareMetrics.recordNdpStatus(NanStatusType.INTERNAL_FAILURE, 866 nnri.networkSpecifier.isOutOfBand(), ndpInfo.startTimestamp); 867 mMgr.endDataPath(ndpId); 868 nnri.ndpInfos.remove(ndpId); 869 if (nnri.specifiedPeerDiscoveryMac != null) { 870 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 871 mNetworkRequestsCache.remove(nnri.networkSpecifier); 872 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 873 } 874 } 875 876 private class WifiAwareNetworkFactory extends NetworkFactory { 877 // Request received while waiting for confirmation that a canonically identical data-path 878 // (NDP) is in the process of being terminated 879 private boolean mWaitingForTermination = false; 880 WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter)881 WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) { 882 super(looper, context, NETWORK_TAG, filter); 883 } 884 tickleConnectivityIfWaiting()885 public void tickleConnectivityIfWaiting() { 886 if (mWaitingForTermination) { 887 if (VDBG) Log.v(TAG, "tickleConnectivityIfWaiting: was waiting!"); 888 mWaitingForTermination = false; 889 reevaluateAllRequests(); 890 } 891 } 892 893 @Override acceptRequest(NetworkRequest request)894 public boolean acceptRequest(NetworkRequest request) { 895 if (VDBG) { 896 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request); 897 } 898 899 NetworkSpecifier networkSpecifierBase = request.getNetworkSpecifier(); 900 if (!(networkSpecifierBase instanceof WifiAwareNetworkSpecifier)) { 901 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 902 + " - not a WifiAwareNetworkSpecifier"); 903 return false; 904 } 905 906 if (!mMgr.isUsageEnabled()) { 907 if (VDBG) { 908 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 909 + " -- Aware disabled"); 910 } 911 releaseRequestAsUnfulfillableByAnyFactory(request); 912 return false; 913 } 914 915 if (mInterfaces.isEmpty()) { 916 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 917 + " -- No Aware interfaces are up"); 918 releaseRequestAsUnfulfillableByAnyFactory(request); 919 return false; 920 } 921 922 WifiAwareNetworkSpecifier networkSpecifier = 923 (WifiAwareNetworkSpecifier) networkSpecifierBase; 924 925 // look up specifier - are we being called again? 926 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 927 if (nnri != null) { 928 if (VDBG) { 929 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 930 + " - already in cache with state=" + nnri.state); 931 } 932 933 if (nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) { 934 mWaitingForTermination = true; 935 return false; 936 } 937 938 // seems to happen after a network agent is created - trying to rematch all 939 // requests again!? 940 return true; 941 } 942 943 nnri = AwareNetworkRequestInformation.processNetworkSpecifier(request, networkSpecifier, 944 mMgr, mWifiPermissionsUtil, mPermissionsWrapper, 945 mAllowNdpResponderFromAnyOverride); 946 if (nnri == null) { 947 Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 948 + " - can't parse network specifier"); 949 releaseRequestAsUnfulfillableByAnyFactory(request); 950 return false; 951 } 952 953 // check to see if a canonical version exists 954 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> primaryRequest = 955 getNetworkRequestByCanonicalDescriptor(nnri.getCanonicalDescriptor()); 956 if (primaryRequest != null) { 957 if (VDBG) { 958 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 959 + ", already has a primary request=" + primaryRequest.getKey() 960 + " with state=" + primaryRequest.getValue().state); 961 } 962 963 if (primaryRequest.getValue().state 964 == AwareNetworkRequestInformation.STATE_TERMINATING) { 965 mWaitingForTermination = true; 966 } else { 967 primaryRequest.getValue().updateToSupportNewRequest(request); 968 } 969 return false; 970 } 971 972 mNetworkRequestsCache.put(networkSpecifier, nnri); 973 mAwareMetrics.recordNdpRequestType(networkSpecifier.type); 974 975 return true; 976 } 977 978 @Override needNetworkFor(NetworkRequest networkRequest)979 protected void needNetworkFor(NetworkRequest networkRequest) { 980 if (mDbg) { 981 Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 982 + networkRequest); 983 } 984 985 NetworkSpecifier networkSpecifierObj = networkRequest.getNetworkSpecifier(); 986 WifiAwareNetworkSpecifier networkSpecifier = null; 987 if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) { 988 networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj; 989 } 990 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 991 if (nnri == null) { 992 Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 993 + networkRequest + " not in cache!?"); 994 return; 995 } 996 997 if (nnri.state != AwareNetworkRequestInformation.STATE_IDLE) { 998 if (VDBG) { 999 Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 1000 + networkRequest + " - already in progress"); 1001 // TODO: understand how/when can be called again/while in progress (seems 1002 // to be related to score re-calculation after a network agent is created) 1003 } 1004 return; 1005 } 1006 if (nnri.networkSpecifier.role 1007 == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) { 1008 nnri.interfaceName = selectInterfaceForRequest(nnri); 1009 if (nnri.interfaceName == null) { 1010 Log.w(TAG, "needNetworkFor: request " + networkSpecifier 1011 + " no interface available"); 1012 mNetworkRequestsCache.remove(networkSpecifier); 1013 letAppKnowThatRequestsAreUnavailable(nnri); 1014 return; 1015 } 1016 1017 mMgr.initiateDataPathSetup(networkSpecifier, nnri.specifiedPeerInstanceId, 1018 NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED, selectChannelForRequest(nnri), 1019 nnri.specifiedPeerDiscoveryMac, nnri.interfaceName, 1020 nnri.networkSpecifier.pmk, nnri.networkSpecifier.passphrase, 1021 nnri.networkSpecifier.isOutOfBand(), null); 1022 nnri.state = 1023 AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE; 1024 } else { 1025 nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST; 1026 } 1027 } 1028 1029 @Override releaseNetworkFor(NetworkRequest networkRequest)1030 protected void releaseNetworkFor(NetworkRequest networkRequest) { 1031 if (mDbg) { 1032 Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 1033 + networkRequest); 1034 } 1035 1036 NetworkSpecifier networkSpecifierObj = networkRequest.getNetworkSpecifier(); 1037 WifiAwareNetworkSpecifier networkSpecifier = null; 1038 if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) { 1039 networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj; 1040 } 1041 1042 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 1043 if (nnri == null) { 1044 Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 1045 + networkRequest + " not in cache!?"); 1046 return; 1047 } 1048 1049 if (nnri.networkAgent != null) { 1050 if (VDBG) { 1051 Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 1052 + networkRequest + ", nnri=" + nnri 1053 + ": agent already created - deferring ending data-path to agent" 1054 + ".unwanted()"); 1055 } 1056 return; 1057 } 1058 1059 /* 1060 * Since there's no agent it means we're in the process of setting up the NDP. 1061 * However, it is possible that there were other equivalent requests for this NDP. We 1062 * should keep going in that case. 1063 */ 1064 nnri.removeSupportForRequest(networkRequest); 1065 if (nnri.equivalentRequests.isEmpty()) { 1066 if (mDbg) { 1067 Log.v(TAG, "releaseNetworkFor: there are no further requests, networkRequest=" 1068 + networkRequest); 1069 } 1070 if (nnri.ndpInfos.size() != 0) { 1071 if (VDBG) Log.v(TAG, "releaseNetworkFor: in progress NDP being terminated"); 1072 for (int index = 0; index < nnri.ndpInfos.size(); index++) { 1073 mMgr.endDataPath(nnri.ndpInfos.keyAt(index)); 1074 } 1075 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 1076 } else { 1077 mNetworkRequestsCache.remove(networkSpecifier); 1078 } 1079 } else { 1080 if (VDBG) { 1081 Log.v(TAG, "releaseNetworkFor: equivalent requests exist - not terminating " 1082 + "networkRequest=" + networkRequest); 1083 } 1084 } 1085 } 1086 letAppKnowThatRequestsAreUnavailable(AwareNetworkRequestInformation nnri)1087 void letAppKnowThatRequestsAreUnavailable(AwareNetworkRequestInformation nnri) { 1088 for (NetworkRequest nr : nnri.equivalentRequests) { 1089 releaseRequestAsUnfulfillableByAnyFactory(nr); 1090 } 1091 } 1092 } 1093 1094 /** 1095 * Network agent for Wi-Fi Aware. 1096 */ 1097 @VisibleForTesting 1098 public class WifiAwareNetworkAgent extends NetworkAgent { 1099 private final AwareNetworkRequestInformation mAwareNetworkRequestInfo; 1100 @VisibleForTesting 1101 public final NetworkCapabilities mDataPathCapabilities; 1102 WifiAwareNetworkAgent(Looper looper, Context context, String logTag, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, NetworkProvider provider, AwareNetworkRequestInformation anri)1103 WifiAwareNetworkAgent(Looper looper, Context context, String logTag, 1104 NetworkCapabilities nc, LinkProperties lp, int score, 1105 NetworkAgentConfig config, NetworkProvider provider, 1106 AwareNetworkRequestInformation anri) { 1107 super(context, looper, logTag, nc, lp, score, config, provider); 1108 mAwareNetworkRequestInfo = anri; 1109 mDataPathCapabilities = nc; 1110 register(); 1111 } 1112 1113 @Override onNetworkUnwanted()1114 public void onNetworkUnwanted() { 1115 if (mDbg) { 1116 Log.v(TAG, "WifiAwareNetworkAgent.unwanted: request=" + mAwareNetworkRequestInfo); 1117 } 1118 for (int index = 0; index < mAwareNetworkRequestInfo.ndpInfos.size(); index++) { 1119 mMgr.endDataPath(mAwareNetworkRequestInfo.ndpInfos.keyAt(index)); 1120 } 1121 mAwareNetworkRequestInfo.state = AwareNetworkRequestInformation.STATE_TERMINATING; 1122 1123 // Will get a callback (on both initiator and responder) when data-path actually 1124 // terminated. At that point will inform the agent and will clear the cache. 1125 } 1126 reconfigureAgentAsDisconnected()1127 void reconfigureAgentAsDisconnected() { 1128 if (mDbg) { 1129 Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: request=" 1130 + mAwareNetworkRequestInfo); 1131 } 1132 unregister(); 1133 } 1134 } 1135 tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri)1136 private void tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri) { 1137 if (VDBG) Log.v(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri); 1138 1139 if (!TextUtils.isEmpty(nnri.interfaceName)) { 1140 boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri); 1141 if (interfaceUsedByAnotherNdp) { 1142 if (mDbg) { 1143 Log.v(TAG, "tearDownInterfaceIfPossible: interfaceName=" + nnri.interfaceName 1144 + ", still in use - not turning down"); 1145 } 1146 } else { 1147 try { 1148 mNetdWrapper.setInterfaceDown(nnri.interfaceName); 1149 } catch (Exception e) { // NwService throws runtime exceptions for errors 1150 Log.e(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri 1151 + ": can't bring interface down - " + e); 1152 } 1153 } 1154 } 1155 1156 if (nnri.networkAgent == null) { 1157 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); 1158 } else { 1159 nnri.networkAgent.reconfigureAgentAsDisconnected(); 1160 } 1161 } 1162 isInterfaceUpAndUsedByAnotherNdp(AwareNetworkRequestInformation nri)1163 private boolean isInterfaceUpAndUsedByAnotherNdp(AwareNetworkRequestInformation nri) { 1164 for (AwareNetworkRequestInformation lnri : mNetworkRequestsCache.values()) { 1165 if (lnri == nri) { 1166 continue; 1167 } 1168 1169 if (nri.interfaceName.equals(lnri.interfaceName) && ( 1170 lnri.state == AwareNetworkRequestInformation.STATE_CONFIRMED 1171 || lnri.state == AwareNetworkRequestInformation.STATE_TERMINATING)) { 1172 return true; 1173 } 1174 } 1175 1176 return false; 1177 } 1178 1179 /** 1180 * Select one of the existing interfaces for the new network request. A request is canonical 1181 * (otherwise it wouldn't be executed). 1182 * 1183 * Criteria: 1184 * 1. Select a network interface which is unused. This is because the network stack does not 1185 * support multiple networks per interface. 1186 * 2. If no network interface is available then (based on a device overlay) either fail (new 1187 * behavior) or (preserve legacy behavior) pick an interface which isn't used for 1188 * communication to the same peer. 1189 */ selectInterfaceForRequest(AwareNetworkRequestInformation req)1190 private String selectInterfaceForRequest(AwareNetworkRequestInformation req) { 1191 SortedSet<String> unused = new TreeSet<>(mInterfaces); 1192 Set<String> invalid = new HashSet<>(); 1193 SortedSet<String> inuse = new TreeSet<>(); 1194 1195 if (mDbg) { 1196 Log.v(TAG, "selectInterfaceForRequest: req=" + req + ", mNetworkRequestsCache=" 1197 + mNetworkRequestsCache); 1198 } 1199 1200 for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) { 1201 if (nnri == req || nnri.interfaceName == null) { 1202 continue; 1203 } 1204 1205 if (Arrays.equals(req.specifiedPeerDiscoveryMac, nnri.specifiedPeerDiscoveryMac)) { 1206 invalid.add(nnri.interfaceName); 1207 } else { 1208 inuse.add(nnri.interfaceName); 1209 } 1210 unused.remove(nnri.interfaceName); 1211 } 1212 1213 if (VDBG) { 1214 Log.v(TAG, "selectInterfaceForRequest: unUsed=" + unused + ", inuse=" + inuse 1215 + ", invalid" + invalid + ", allInterfaces" + mInterfaces); 1216 } 1217 1218 // If any interface is unused, pick it first 1219 if (!unused.isEmpty()) { 1220 return unused.first(); 1221 } 1222 1223 // If device doesn't allow to make multiple network on same interface, return null. 1224 if (!mContext.getResources() 1225 .getBoolean(R.bool.config_wifiAllowMultipleNetworksOnSameAwareNdi)) { 1226 Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - no interfaces available!"); 1227 return null; 1228 } 1229 1230 for (String iface : inuse) { 1231 if (!invalid.contains(iface)) { 1232 return iface; 1233 } 1234 } 1235 1236 Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - no interfaces available!"); 1237 return null; 1238 } 1239 1240 /** 1241 * Select a channel for the network request. 1242 * 1243 * TODO (b/38209409): The value from this function isn't currently used - the channel selection 1244 * is delegated to the HAL. 1245 */ selectChannelForRequest(AwareNetworkRequestInformation req)1246 private int selectChannelForRequest(AwareNetworkRequestInformation req) { 1247 return 2437; 1248 } 1249 1250 private static class NdpInfo { 1251 static final int STATE_WAIT_FOR_CONFIRM = 107; 1252 static final int STATE_CONFIRMED = 108; 1253 static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 109; 1254 1255 public int state; 1256 1257 public byte[] peerDiscoveryMac = null; 1258 public int peerInstanceId = 0; 1259 public int ndpId = 0; // 0 is never a valid ID! 1260 public byte[] peerDataMac; 1261 public Inet6Address peerIpv6; 1262 public int peerPort = 0; // uninitialized (invalid) value 1263 public int peerTransportProtocol = -1; // uninitialized (invalid) value 1264 public byte[] peerIpv6Override = null; 1265 public List<NanDataPathChannelInfo> channelInfo; 1266 public long startTimestamp = 0; // request is made (initiator) / get request (responder) 1267 NdpInfo(int ndpId)1268 NdpInfo(int ndpId) { 1269 this.ndpId = ndpId; 1270 } 1271 1272 @Override toString()1273 public String toString() { 1274 StringBuilder sb = new StringBuilder(); 1275 sb.append(", ndpInfo["); 1276 sb.append("ndpId=").append(ndpId).append(", peerInstanceId=").append( 1277 peerInstanceId).append(", peerDiscoveryMac=").append( 1278 peerDiscoveryMac == null ? "" 1279 : String.valueOf(HexEncoding.encode(peerDiscoveryMac))) 1280 .append(", peerDataMac=").append( 1281 peerDataMac == null ? "" 1282 : String.valueOf(HexEncoding.encode(peerDataMac))) 1283 .append(", peerIpv6=").append(peerIpv6).append( 1284 ", peerPort=").append( 1285 peerPort).append(", peerTransportProtocol=").append( 1286 peerTransportProtocol).append(", startTimestamp=").append( 1287 startTimestamp).append(", channelInfo=").append( 1288 channelInfo); 1289 sb.append("]"); 1290 return sb.toString(); 1291 } 1292 } 1293 1294 /** 1295 * Aware network request. State object: contains network request information/state through its 1296 * lifetime. 1297 */ 1298 @VisibleForTesting 1299 public static class AwareNetworkRequestInformation { 1300 static final int STATE_IDLE = 100; 1301 static final int STATE_CONFIRMED = 101; 1302 static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 102; 1303 static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 103; 1304 static final int STATE_TERMINATING = 104; 1305 static final int STATE_IN_SETUP = 105; 1306 1307 public int state; 1308 1309 public int uid; 1310 public String packageName; 1311 public String interfaceName; 1312 public int pubSubId = 0; 1313 public int specifiedPeerInstanceId = 0; 1314 public byte[] specifiedPeerDiscoveryMac = null; 1315 public WifiAwareNetworkSpecifier networkSpecifier; 1316 public long startValidationTimestamp = 0; // NDP created and starting to validate IPv6 addr 1317 public SparseArray<NdpInfo> ndpInfos = new SparseArray(); 1318 1319 public WifiAwareNetworkAgent networkAgent; 1320 1321 /* A collection of request which are equivalent to the current request and are 1322 * supported by it's agent. This list DOES include the original (first) network request 1323 * (whose specifier is also stored separately above). 1324 */ 1325 public Set<NetworkRequest> equivalentRequests = new HashSet<>(); 1326 updateToSupportNewRequest(NetworkRequest ns)1327 void updateToSupportNewRequest(NetworkRequest ns) { 1328 if (VDBG) Log.v(TAG, "updateToSupportNewRequest: ns=" + ns); 1329 if (equivalentRequests.add(ns) && state == STATE_CONFIRMED) { 1330 if (networkAgent == null) { 1331 Log.wtf(TAG, "updateToSupportNewRequest: null agent in CONFIRMED state!?"); 1332 return; 1333 } 1334 1335 networkAgent.sendNetworkCapabilities(getNetworkCapabilities()); 1336 } 1337 } 1338 removeSupportForRequest(NetworkRequest ns)1339 void removeSupportForRequest(NetworkRequest ns) { 1340 if (VDBG) Log.v(TAG, "removeSupportForRequest: ns=" + ns); 1341 equivalentRequests.remove(ns); 1342 1343 // we will not update the agent: 1344 // 1. this will only get called before the agent is created 1345 // 2. connectivity service does not allow (WTF) updates with reduced capabilities 1346 } 1347 getNetworkCapabilities()1348 private NetworkCapabilities getNetworkCapabilities() { 1349 final NetworkCapabilities.Builder builder = 1350 new NetworkCapabilities.Builder(sNetworkCapabilitiesFilter); 1351 builder.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier( 1352 equivalentRequests.stream() 1353 .map(NetworkRequest::getNetworkSpecifier) 1354 .toArray(WifiAwareNetworkSpecifier[]::new))); 1355 1356 if (ndpInfos.size() == 0) { 1357 Log.wtf(TAG, "Number of NDPs is 0 when Network agent is created?! " 1358 + "AwareNetworkRequestInformation" + this); 1359 return builder.setTransportInfo(new WifiAwareNetworkInfo()).build(); 1360 } 1361 if (ndpInfos.valueAt(0).peerIpv6 != null) { 1362 builder.setTransportInfo( 1363 new WifiAwareNetworkInfo(ndpInfos.valueAt(0).peerIpv6, 1364 ndpInfos.valueAt(0).peerPort, 1365 ndpInfos.valueAt(0).peerTransportProtocol)); 1366 } 1367 return builder.build(); 1368 } 1369 1370 /** 1371 * Returns a canonical descriptor for the network request. 1372 */ getCanonicalDescriptor()1373 CanonicalConnectionInfo getCanonicalDescriptor() { 1374 return new CanonicalConnectionInfo(specifiedPeerDiscoveryMac, networkSpecifier.pmk, 1375 networkSpecifier.sessionId, networkSpecifier.passphrase); 1376 } 1377 processNetworkSpecifier(NetworkRequest request, WifiAwareNetworkSpecifier ns, WifiAwareStateManager mgr, WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionWrapper, boolean allowNdpResponderFromAnyOverride)1378 static AwareNetworkRequestInformation processNetworkSpecifier(NetworkRequest request, 1379 WifiAwareNetworkSpecifier ns, WifiAwareStateManager mgr, 1380 WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionWrapper, 1381 boolean allowNdpResponderFromAnyOverride) { 1382 int uid, pubSubId = 0; 1383 int peerInstanceId = 0; 1384 String packageName = null; 1385 byte[] peerMac = ns.peerMac; 1386 1387 if (VDBG) { 1388 Log.v(TAG, "processNetworkSpecifier: networkSpecifier=" + ns); 1389 } 1390 1391 // type: always valid 1392 if (ns.type < 0 1393 || ns.type > WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_MAX_VALID) { 1394 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1395 + ", invalid 'type' value"); 1396 return null; 1397 } 1398 1399 // role: always valid 1400 if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 1401 && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) { 1402 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1403 + " -- invalid 'role' value"); 1404 return null; 1405 } 1406 1407 if (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 1408 && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB 1409 && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) { 1410 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1411 + " -- invalid 'type' value for INITIATOR (only IB and OOB are " 1412 + "permitted)"); 1413 return null; 1414 } 1415 1416 // look up network specifier information in Aware state manager 1417 WifiAwareClientState client = mgr.getClient(ns.clientId); 1418 if (client == null) { 1419 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1420 + " -- not client with this id -- clientId=" + ns.clientId); 1421 return null; 1422 } 1423 uid = client.getUid(); 1424 packageName = client.getCallingPackage(); 1425 1426 // API change post 30: allow accepts any peer responder. 1427 1428 if (!SdkLevel.isAtLeastS() && !allowNdpResponderFromAnyOverride 1429 && !wifiPermissionsUtil.isTargetSdkLessThan( 1430 client.getCallingPackage(), Build.VERSION_CODES.P, uid)) { 1431 if (ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB 1432 && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) { 1433 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1434 + " -- no ANY specifications allowed for this API level"); 1435 return null; 1436 } 1437 } 1438 1439 // validate the port & transportProtocol 1440 if (ns.port < 0 || ns.transportProtocol < -1) { 1441 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1442 + " -- invalid port/transportProtocol"); 1443 return null; 1444 } 1445 if (ns.port != 0 || ns.transportProtocol != -1) { 1446 if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) { 1447 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1448 + " -- port/transportProtocol can only be specified on responder"); 1449 return null; 1450 } 1451 if (TextUtils.isEmpty(ns.passphrase) && ns.pmk == null) { 1452 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1453 + " -- port/transportProtocol can only be specified on secure ndp"); 1454 return null; 1455 } 1456 } 1457 1458 // validate the role (if session ID provided: i.e. session 1xx) 1459 if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB 1460 || ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) { 1461 WifiAwareDiscoverySessionState session = client.getSession(ns.sessionId); 1462 if (session == null) { 1463 Log.e(TAG, 1464 "processNetworkSpecifier: networkSpecifier=" + ns 1465 + " -- no session with this id -- sessionId=" + ns.sessionId); 1466 return null; 1467 } 1468 1469 if ((session.isPublishSession() 1470 && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || ( 1471 !session.isPublishSession() && ns.role 1472 != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) { 1473 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1474 + " -- invalid role for session type"); 1475 return null; 1476 } 1477 1478 if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB) { 1479 pubSubId = session.getPubSubId(); 1480 WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo( 1481 ns.peerId); 1482 if (peerInfo == null) { 1483 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1484 + " -- no peer info associated with this peer id -- peerId=" 1485 + ns.peerId); 1486 return null; 1487 } 1488 peerInstanceId = peerInfo.mInstanceId; 1489 try { 1490 peerMac = peerInfo.mMac; 1491 if (peerMac == null || peerMac.length != 6) { 1492 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" 1493 + ns + " -- invalid peer MAC address"); 1494 return null; 1495 } 1496 } catch (IllegalArgumentException e) { 1497 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1498 + " -- invalid peer MAC address -- e=" + e); 1499 return null; 1500 } 1501 } 1502 } 1503 1504 // validate UID && package name 1505 if (request.getRequestorUid() != uid 1506 || !TextUtils.equals(request.getRequestorPackageName(), packageName)) { 1507 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() 1508 + " -- UID or package name mismatch to clientId's uid=" + uid 1509 + ", packageName=" + packageName); 1510 return null; 1511 } 1512 1513 // validate passphrase & PMK (if provided) 1514 if (!TextUtils.isEmpty(ns.passphrase)) { // non-null indicates usage 1515 if (!WifiAwareUtils.validatePassphrase(ns.passphrase)) { 1516 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() 1517 + " -- invalid passphrase length: " + ns.passphrase.length()); 1518 return null; 1519 } 1520 } 1521 if (ns.pmk != null && !WifiAwareUtils.validatePmk(ns.pmk)) { // non-null indicates usage 1522 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() 1523 + " -- invalid pmk length: " + ns.pmk.length); 1524 return null; 1525 } 1526 1527 // create container and populate 1528 AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation(); 1529 nnri.state = AwareNetworkRequestInformation.STATE_IDLE; 1530 nnri.uid = uid; 1531 nnri.packageName = packageName; 1532 nnri.pubSubId = pubSubId; 1533 nnri.specifiedPeerInstanceId = peerInstanceId; 1534 nnri.specifiedPeerDiscoveryMac = peerMac; 1535 nnri.networkSpecifier = ns; 1536 nnri.equivalentRequests.add(request); 1537 1538 return nnri; 1539 } 1540 1541 @Override toString()1542 public String toString() { 1543 StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: "); 1544 sb.append("state=").append(state).append(", ns=").append(networkSpecifier) 1545 .append(", uid=").append(uid) 1546 .append(", packageName=").append(packageName) 1547 .append(", interfaceName=").append(interfaceName).append( 1548 ", pubSubId=").append(pubSubId).append(", specifiedPeerInstanceId=").append( 1549 specifiedPeerInstanceId).append(", specifiedPeerDiscoveryMac=").append( 1550 specifiedPeerDiscoveryMac == null ? "" 1551 : String.valueOf(HexEncoding.encode(specifiedPeerDiscoveryMac))) 1552 .append(", equivalentSpecifiers=["); 1553 for (NetworkRequest nr : equivalentRequests) { 1554 sb.append(nr.toString()).append(", "); 1555 } 1556 sb.append("]"); 1557 sb.append(", NdpInfos["); 1558 for (int index = 0; index < ndpInfos.size(); index++) { 1559 sb.append(" ").append(index).append(": ").append(ndpInfos.valueAt(index)); 1560 } 1561 sb.append("]"); 1562 return sb.toString(); 1563 } 1564 } 1565 1566 /** 1567 * A canonical (unique) descriptor of the peer connection. 1568 */ 1569 static class CanonicalConnectionInfo { CanonicalConnectionInfo(byte[] peerDiscoveryMac, byte[] pmk, int sessionId, String passphrase)1570 CanonicalConnectionInfo(byte[] peerDiscoveryMac, byte[] pmk, int sessionId, 1571 String passphrase) { 1572 this.peerDiscoveryMac = peerDiscoveryMac; 1573 this.pmk = pmk; 1574 this.sessionId = sessionId; 1575 this.passphrase = passphrase; 1576 } 1577 1578 public final byte[] peerDiscoveryMac; 1579 1580 /* 1581 * Security configuration matching: 1582 * - open: pmk/passphrase = null 1583 * - pmk: pmk != null, passphrase = null 1584 * - passphrase: passphrase != null, sessionId used (==0 for OOB), pmk=null 1585 */ 1586 public final byte[] pmk; 1587 1588 public final int sessionId; 1589 public final String passphrase; 1590 matches(CanonicalConnectionInfo other)1591 public boolean matches(CanonicalConnectionInfo other) { 1592 return Arrays.equals(peerDiscoveryMac, other.peerDiscoveryMac) 1593 && Arrays.equals(pmk, other.pmk) 1594 && TextUtils.equals(passphrase, other.passphrase) 1595 && (TextUtils.isEmpty(passphrase) || sessionId == other.sessionId); 1596 } 1597 1598 @Override toString()1599 public String toString() { 1600 StringBuilder sb = new StringBuilder("CanonicalConnectionInfo: ["); 1601 sb.append("peerDiscoveryMac=").append(peerDiscoveryMac == null ? "" 1602 : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(", pmk=").append( 1603 pmk == null ? "" : "*").append(", sessionId=").append(sessionId).append( 1604 ", passphrase=").append(passphrase == null ? "" : "*").append("]"); 1605 return sb.toString(); 1606 } 1607 } 1608 1609 /** 1610 * Enables mocking. 1611 */ 1612 @VisibleForTesting 1613 public class NetworkInterfaceWrapper { 1614 /** 1615 * Configures network agent properties: link-local address, connected status, interface 1616 * name. Delegated to enable mocking. 1617 */ configureAgentProperties(AwareNetworkRequestInformation nnri, NetworkCapabilities.Builder ncBuilder, LinkProperties linkProperties)1618 public boolean configureAgentProperties(AwareNetworkRequestInformation nnri, 1619 NetworkCapabilities.Builder ncBuilder, LinkProperties linkProperties) { 1620 // find link-local address 1621 InetAddress linkLocal = null; 1622 NetworkInterface ni; 1623 try { 1624 ni = NetworkInterface.getByName(nnri.interfaceName); 1625 } catch (SocketException e) { 1626 Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 1627 + ": can't get network interface - " + e); 1628 return false; 1629 } 1630 if (ni == null) { 1631 Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 1632 + ": can't get network interface (null)"); 1633 return false; 1634 } 1635 Enumeration<InetAddress> addresses = ni.getInetAddresses(); 1636 while (addresses.hasMoreElements()) { 1637 InetAddress ip = addresses.nextElement(); 1638 if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) { 1639 linkLocal = ip; 1640 break; 1641 } 1642 } 1643 1644 if (linkLocal == null) { 1645 Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses"); 1646 return false; 1647 } 1648 1649 ncBuilder.setRequestorUid(nnri.uid); 1650 ncBuilder.setRequestorPackageName(nnri.packageName); 1651 ncBuilder.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier( 1652 nnri.equivalentRequests.stream() 1653 .map(NetworkRequest::getNetworkSpecifier) 1654 .toArray(WifiAwareNetworkSpecifier[]::new))); 1655 1656 linkProperties.setInterfaceName(nnri.interfaceName); 1657 linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64)); 1658 linkProperties.addRoute( 1659 new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName, 1660 RTN_UNICAST)); 1661 1662 return true; 1663 } 1664 1665 /** 1666 * Tries binding to the input address to check whether it is configured (and therefore 1667 * usable). 1668 */ isAddressUsable(LinkProperties linkProperties)1669 public boolean isAddressUsable(LinkProperties linkProperties) { 1670 InetAddress address = linkProperties.getLinkAddresses().get(0).getAddress(); 1671 DatagramSocket testDatagramSocket = null; 1672 try { 1673 testDatagramSocket = new DatagramSocket(0, address); 1674 } catch (SocketException e) { 1675 if (mDbg) { 1676 Log.v(TAG, "Can't create socket on address " + address + " -- " + e); 1677 } 1678 return false; 1679 } finally { 1680 if (testDatagramSocket != null) { 1681 testDatagramSocket.close(); 1682 } 1683 } 1684 return true; 1685 } 1686 1687 /** 1688 * Tell the network agent the network is now connected. 1689 */ setConnected(WifiAwareNetworkAgent networkAgent)1690 public void setConnected(WifiAwareNetworkAgent networkAgent) { 1691 networkAgent.markConnected(); 1692 } 1693 } 1694 1695 /** 1696 * Utility (hence static) class encapsulating the data structure used to communicate Wi-Fi Aware 1697 * specific network capabilities. The TLV is defined as part of the NANv3 spec: 1698 * 1699 * - Generic Service Protocol 1700 * - Port 1701 * - Transport protocol 1702 */ 1703 @VisibleForTesting 1704 public static class NetworkInformationData { 1705 // All package visible to allow usage in unit testing 1706 /* package */ static final int IPV6_LL_TYPE = 0x00; // Table 82 1707 /* package */ static final int SERVICE_INFO_TYPE = 0x01; // Table 83 1708 /* package */ static final byte[] WFA_OUI = {0x50, 0x6F, (byte) 0x9A}; // Table 83 1709 /* package */ static final int GENERIC_SERVICE_PROTOCOL_TYPE = 0x02; // Table 50 1710 /* package */ static final int SUB_TYPE_PORT = 0x00; // Table 127 1711 /* package */ static final int SUB_TYPE_TRANSPORT_PROTOCOL = 0x01; // Table 128 1712 1713 /** 1714 * Construct the TLV. 1715 */ buildTlv(int port, int transportProtocol)1716 public static byte[] buildTlv(int port, int transportProtocol) { 1717 if (port == 0 && transportProtocol == -1) { 1718 return null; 1719 } 1720 1721 TlvBufferUtils.TlvConstructor tlvc = new TlvBufferUtils.TlvConstructor(1, 2); 1722 tlvc.setByteOrder(ByteOrder.LITTLE_ENDIAN); 1723 tlvc.allocate(20); // safe size for now 1724 1725 tlvc.putRawByteArray(WFA_OUI); 1726 tlvc.putRawByte((byte) GENERIC_SERVICE_PROTOCOL_TYPE); 1727 1728 if (port != 0) { 1729 tlvc.putShort(SUB_TYPE_PORT, (short) port); 1730 } 1731 if (transportProtocol != -1) { 1732 tlvc.putByte(SUB_TYPE_TRANSPORT_PROTOCOL, (byte) transportProtocol); 1733 } 1734 1735 byte[] subTypes = tlvc.getArray(); 1736 1737 tlvc.allocate(20); 1738 tlvc.putByteArray(SERVICE_INFO_TYPE, subTypes); 1739 1740 return tlvc.getArray(); 1741 } 1742 1743 static class ParsedResults { ParsedResults(int port, int transportProtocol, byte[] ipv6Override)1744 ParsedResults(int port, int transportProtocol, byte[] ipv6Override) { 1745 this.port = port; 1746 this.transportProtocol = transportProtocol; 1747 this.ipv6Override = ipv6Override; 1748 } 1749 1750 public int port = 0; 1751 public int transportProtocol = -1; 1752 public byte[] ipv6Override = null; 1753 } 1754 1755 /** 1756 * Parse the TLV and returns: 1757 * - Null on parsing error 1758 * - <port | 0, transport-protocol | -1, ipv6-override | null> otherwise 1759 */ parseTlv(byte[] tlvs)1760 public static ParsedResults parseTlv(byte[] tlvs) { 1761 int port = 0; 1762 int transportProtocol = -1; 1763 byte[] ipv6Override = null; 1764 1765 try { 1766 TlvBufferUtils.TlvIterable tlvi = new TlvBufferUtils.TlvIterable(1, 2, tlvs); 1767 tlvi.setByteOrder(ByteOrder.LITTLE_ENDIAN); 1768 for (TlvBufferUtils.TlvElement tlve : tlvi) { 1769 switch (tlve.type) { 1770 case IPV6_LL_TYPE: 1771 if (tlve.length != 8) { // 8 bytes in IPv6 address 1772 Log.e(TAG, "NetworkInformationData: invalid IPv6 TLV -- length: " 1773 + tlve.length); 1774 return null; 1775 } 1776 ipv6Override = tlve.getRawData(); 1777 break; 1778 case SERVICE_INFO_TYPE: 1779 Pair<Integer, Integer> serviceInfo = parseServiceInfoTlv( 1780 tlve.getRawData()); 1781 if (serviceInfo == null) { 1782 return null; 1783 } 1784 port = serviceInfo.first; 1785 transportProtocol = serviceInfo.second; 1786 break; 1787 default: 1788 Log.w(TAG, 1789 "NetworkInformationData: ignoring unknown T -- " + tlve.type); 1790 break; 1791 } 1792 } 1793 } catch (Exception e) { 1794 Log.e(TAG, "NetworkInformationData: error parsing TLV -- " + e); 1795 return null; 1796 } 1797 return new ParsedResults(port, transportProtocol, ipv6Override); 1798 } 1799 1800 /** 1801 * Parse the Service Info TLV: 1802 * - Returns null on error 1803 * - Returns <port | 0, transport-protocol | -1> otherwise 1804 */ parseServiceInfoTlv(byte[] tlv)1805 private static Pair<Integer, Integer> parseServiceInfoTlv(byte[] tlv) { 1806 int port = 0; 1807 int transportProtocol = -1; 1808 1809 if (tlv.length < 4) { 1810 Log.e(TAG, "NetworkInformationData: invalid SERVICE_INFO_TYPE length"); 1811 return null; 1812 } 1813 if (tlv[0] != WFA_OUI[0] || tlv[1] != WFA_OUI[1] || tlv[2] != WFA_OUI[2]) { 1814 Log.e(TAG, "NetworkInformationData: unexpected OUI"); 1815 return null; 1816 } 1817 if (tlv[3] != GENERIC_SERVICE_PROTOCOL_TYPE) { 1818 Log.e(TAG, "NetworkInformationData: invalid type -- " + tlv[3]); 1819 return null; 1820 } 1821 TlvBufferUtils.TlvIterable subTlvi = new TlvBufferUtils.TlvIterable(1, 1822 2, Arrays.copyOfRange(tlv, 4, tlv.length)); 1823 subTlvi.setByteOrder(ByteOrder.LITTLE_ENDIAN); 1824 for (TlvBufferUtils.TlvElement subTlve : subTlvi) { 1825 switch (subTlve.type) { 1826 case SUB_TYPE_PORT: 1827 if (subTlve.length != 2) { 1828 Log.e(TAG, 1829 "NetworkInformationData: invalid port TLV " 1830 + "length -- " + subTlve.length); 1831 return null; 1832 } 1833 port = subTlve.getShort(); 1834 if (port < 0) { 1835 port += -2 * (int) Short.MIN_VALUE; 1836 } 1837 if (port == 0) { 1838 Log.e(TAG, "NetworkInformationData: invalid port " 1839 + port); 1840 return null; 1841 } 1842 break; 1843 case SUB_TYPE_TRANSPORT_PROTOCOL: 1844 if (subTlve.length != 1) { 1845 Log.e(TAG, "NetworkInformationData: invalid transport " 1846 + "protocol TLV length -- " + subTlve.length); 1847 return null; 1848 } 1849 transportProtocol = subTlve.getByte(); 1850 if (transportProtocol < 0) { 1851 transportProtocol += -2 * (int) Byte.MIN_VALUE; 1852 } 1853 break; 1854 default: 1855 Log.w(TAG, "NetworkInformationData: ignoring unknown " 1856 + "SERVICE_INFO.T -- " + subTlve.type); 1857 break; 1858 } 1859 } 1860 return Pair.create(port, transportProtocol); 1861 } 1862 } 1863 1864 /** 1865 * Dump the internal state of the class. 1866 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)1867 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1868 pw.println("WifiAwareDataPathStateManager:"); 1869 pw.println(" mInterfaces: " + mInterfaces); 1870 pw.println(" sNetworkCapabilitiesFilter: " + sNetworkCapabilitiesFilter); 1871 pw.println(" mNetworkRequestsCache: " + mNetworkRequestsCache); 1872 pw.println(" mNetworkFactory:"); 1873 mNetworkFactory.dump(fd, pw, args); 1874 } 1875 } 1876