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