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