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