blob: b99d987273d9393323b35a60ebfc30c4f8138c53 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wifi;
import android.annotation.Nullable;
import android.net.InetAddresses;
import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.LinkAddress;
import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.StaticIpConfiguration;
import android.net.Uri;
import android.net.wifi.SecurityParams;
import android.net.wifi.WifiConfiguration;
import android.util.Log;
import android.util.Pair;
import com.android.server.wifi.util.XmlUtil;
import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil;
import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* Parser for major version 1 of WiFi backup data.
* Contains whitelists of tags for WifiConfiguration and IpConfiguration sections for each of
* the minor versions.
*
* Overall structure of the major version 1 XML schema:
* <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
* <WifiConfigStore>
* <float name="Version" value="1.0" />
* <NetworkList>
* <Network>
* <WifiConfiguration>
* <string name="ConfigKey">value</string>
* <string name="SSID">value</string>
* <string name="PreSharedKey" />value</string>
* <string-array name="WEPKeys" num="4">
* <item value="WifiConfigStoreWep1" />
* <item value="WifiConfigStoreWep2" />
* <item value="WifiConfigStoreWep3" />
* <item value="WifiConfigStoreWep3" />
* </string-array>
* ... (other supported tag names in minor version 1: "WEPTxKeyIndex", "HiddenSSID",
* "RequirePMF", "AllowedKeyMgmt", "AllowedProtocols", "AllowedAuthAlgos",
* "AllowedGroupCiphers", "AllowedPairwiseCiphers", "Shared")
* </WifiConfiguration>
* <IpConfiguration>
* <string name="IpAssignment">value</string>
* <string name="ProxySettings">value</string>
* ... (other supported tag names in minor version 1: "LinkAddress", "LinkPrefixLength",
* "GatewayAddress", "DNSServers", "ProxyHost", "ProxyPort", "ProxyPac",
* "ProxyExclusionList")
* </IpConfiguration>
* </Network>
* <Network>
* ... (format as above)
* </Network>
* </NetworkList>
* </WifiConfigStore>
*/
class WifiBackupDataV1Parser implements WifiBackupDataParser {
private static final String TAG = "WifiBackupDataV1Parser";
private static final int HIGHEST_SUPPORTED_MINOR_VERSION = 3;
// List of tags supported for <WifiConfiguration> section in minor version 0
private static final Set<String> WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS =
new HashSet<String>(Arrays.asList(new String[] {
WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY,
WifiConfigurationXmlUtil.XML_TAG_SSID,
WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY,
WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS,
WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX,
WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID,
WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF,
WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT,
WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS,
WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS,
WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS,
WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS,
WifiConfigurationXmlUtil.XML_TAG_SHARED,
}));
// List of tags supported for <WifiConfiguration> section in minor version 1
private static final Set<String> WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS =
new HashSet<String>() {{
addAll(WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS);
add(WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE);
}};
// List of tags supported for <WifiConfiguration> section in minor version 2
private static final Set<String> WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS =
new HashSet<String>() {{
addAll(WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS);
add(WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN);
}};
// List of tags supported for <WifiConfiguration> section in minor version 3
private static final Set<String> WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS =
new HashSet<String>() {{
addAll(WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS);
add(WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS_LIST);
add(WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS);
add(WifiConfigurationXmlUtil.XML_TAG_SECURITY_TYPE);
add(WifiConfigurationXmlUtil.XML_TAG_SAE_IS_H2E_ONLY_MODE);
add(WifiConfigurationXmlUtil.XML_TAG_SAE_IS_PK_ONLY_MODE);
add(WifiConfigurationXmlUtil.XML_TAG_IS_ADDED_BY_AUTO_UPGRADE);
add(WifiConfigurationXmlUtil.XML_TAG_DELETION_PRIORITY);
add(WifiConfigurationXmlUtil.XML_TAG_NUM_REBOOTS_SINCE_LAST_USE);
}};
// List of tags supported for <IpConfiguration> section in minor version 0 to 3
private static final Set<String> IP_CONFIGURATION_MINOR_V0_V1_V2_V3_SUPPORTED_TAGS =
new HashSet<String>(Arrays.asList(new String[] {
IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT,
IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS,
IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH,
IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS,
IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES,
IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS,
IpConfigurationXmlUtil.XML_TAG_PROXY_HOST,
IpConfigurationXmlUtil.XML_TAG_PROXY_PORT,
IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST,
IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE,
}));
@Override
public List<WifiConfiguration> parseNetworkConfigurationsFromXml(XmlPullParser in,
int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException {
// clamp down the minorVersion to the highest one that this parser version supports
if (minorVersion > HIGHEST_SUPPORTED_MINOR_VERSION) {
minorVersion = HIGHEST_SUPPORTED_MINOR_VERSION;
}
// Find the configuration list section.
XmlUtil.gotoNextSectionWithName(in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK_LIST,
outerTagDepth);
// Find all the configurations within the configuration list section.
int networkListTagDepth = outerTagDepth + 1;
List<WifiConfiguration> configurations = new ArrayList<>();
while (XmlUtil.gotoNextSectionWithNameOrEnd(
in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK, networkListTagDepth)) {
WifiConfiguration configuration =
parseNetworkConfigurationFromXml(in, minorVersion, networkListTagDepth);
if (configuration != null) {
Log.v(TAG, "Parsed Configuration: " + configuration.getKey());
configurations.add(configuration);
}
}
return configurations;
}
@Override
public int getHighestSupportedMinorVersion() {
return HIGHEST_SUPPORTED_MINOR_VERSION;
}
/**
* Parses the configuration data elements from the provided XML stream to a Configuration.
*
* @param in XmlPullParser instance pointing to the XML stream.
* @param minorVersion minor version number parsed from incoming data.
* @param outerTagDepth depth of the outer tag in the XML document.
* @return WifiConfiguration object if parsing is successful, null otherwise.
*/
private WifiConfiguration parseNetworkConfigurationFromXml(XmlPullParser in, int minorVersion,
int outerTagDepth) throws XmlPullParserException, IOException {
WifiConfiguration configuration = null;
int networkTagDepth = outerTagDepth + 1;
// Retrieve WifiConfiguration object first.
XmlUtil.gotoNextSectionWithName(
in, WifiBackupRestore.XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION,
networkTagDepth);
int configTagDepth = networkTagDepth + 1;
configuration = parseWifiConfigurationFromXml(in, configTagDepth, minorVersion);
if (configuration == null) {
return null;
}
// Now retrieve any IP configuration info.
XmlUtil.gotoNextSectionWithName(
in, WifiBackupRestore.XML_TAG_SECTION_HEADER_IP_CONFIGURATION, networkTagDepth);
IpConfiguration ipConfiguration = parseIpConfigurationFromXml(in, configTagDepth,
minorVersion);
configuration.setIpConfiguration(ipConfiguration);
return configuration;
}
/**
* Helper method to parse the WifiConfiguration object.
*/
private WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in,
int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException {
Pair<String, WifiConfiguration> parsedConfig =
parseWifiConfigurationFromXmlInternal(in, outerTagDepth, minorVersion);
if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) {
return null;
}
String configKeyParsed = parsedConfig.first;
WifiConfiguration configuration = parsedConfig.second;
String configKeyCalculated = configuration.getKey();
if (!configKeyParsed.equals(configKeyCalculated)) {
// configKey is not part of the SDK. So, we can't expect this to be the same
// across OEM's. Just log a warning & continue.
Log.w(TAG, "Configuration key does not match. Retrieved: " + configKeyParsed
+ ", Calculated: " + configKeyCalculated);
}
return configuration;
}
/**
* Helper method to mask out any invalid data in parsed WifiConfiguration.
*
* This is a compatibility layer added to the parsing logic to try and weed out any known
* issues in the backup data format from other OEM's.
*/
private static void clearAnyKnownIssuesInParsedConfiguration(WifiConfiguration config) {
/**
* Fix for b/73987207. Clear any invalid bits in the bitsets.
*/
// |allowedKeyManagement|
if (config.allowedKeyManagement.length()
> WifiConfiguration.KeyMgmt.strings.length) {
config.allowedKeyManagement.clear(
WifiConfiguration.KeyMgmt.strings.length,
config.allowedKeyManagement.length());
}
// |allowedProtocols|
if (config.allowedProtocols.length()
> WifiConfiguration.Protocol.strings.length) {
config.allowedProtocols.clear(
WifiConfiguration.Protocol.strings.length,
config.allowedProtocols.length());
}
// |allowedAuthAlgorithms|
if (config.allowedAuthAlgorithms.length()
> WifiConfiguration.AuthAlgorithm.strings.length) {
config.allowedAuthAlgorithms.clear(
WifiConfiguration.AuthAlgorithm.strings.length,
config.allowedAuthAlgorithms.length());
}
// |allowedGroupCiphers|
if (config.allowedGroupCiphers.length()
> WifiConfiguration.GroupCipher.strings.length) {
config.allowedGroupCiphers.clear(
WifiConfiguration.GroupCipher.strings.length,
config.allowedGroupCiphers.length());
}
// |allowedPairwiseCiphers|
if (config.allowedPairwiseCiphers.length()
> WifiConfiguration.PairwiseCipher.strings.length) {
config.allowedPairwiseCiphers.clear(
WifiConfiguration.PairwiseCipher.strings.length,
config.allowedPairwiseCiphers.length());
}
// Add any other fixable issues discovered from other OEM's here.
}
/**
* Parses the configuration data elements from the provided XML stream to a
* WifiConfiguration object.
* Looping through the tags makes it easy to add elements in the future minor versions if
* needed. Unsupported elements will be ignored.
*
* @param in XmlPullParser instance pointing to the XML stream.
* @param outerTagDepth depth of the outer tag in the XML document.
* @param minorVersion minor version number parsed from incoming data.
* @return Pair<Config key, WifiConfiguration object> if parsing is successful, null otherwise.
*/
private static Pair<String, WifiConfiguration> parseWifiConfigurationFromXmlInternal(
XmlPullParser in, int outerTagDepth, int minorVersion)
throws XmlPullParserException, IOException {
WifiConfiguration configuration = new WifiConfiguration();
String configKeyInData = null;
Set<String> supportedTags = getSupportedWifiConfigurationTags(minorVersion);
// Loop through and parse out all the elements from the stream within this section.
while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
String tagName = null;
Object value = null;
if (in.getAttributeValue(null, "name") != null) {
String[] valueName = new String[1];
value = XmlUtil.readCurrentValue(in, valueName);
tagName = valueName[0];
if (tagName == null) {
throw new XmlPullParserException("Missing value name");
}
} else {
tagName = in.getName();
if (tagName == null) {
throw new XmlPullParserException("Unexpected null tag found");
}
}
// ignore the tags that are not supported up until the current minor version
if (!supportedTags.contains(tagName)) {
Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <WifiConfiguration>"
+ " section, ignoring.");
continue;
}
// note: the below switch case list should contain all tags supported up until the
// highest minor version supported by this parser
switch (tagName) {
case WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY:
configKeyInData = (String) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_SSID:
configuration.SSID = (String) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY:
configuration.preSharedKey = (String) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS:
populateWepKeysFromXmlValue(value, configuration.wepKeys);
break;
case WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX:
configuration.wepTxKeyIndex = (int) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID:
configuration.hiddenSSID = (boolean) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF:
configuration.requirePmf = (boolean) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT:
byte[] allowedKeyMgmt = (byte[]) value;
configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt);
break;
case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS:
byte[] allowedProtocols = (byte[]) value;
configuration.allowedProtocols = BitSet.valueOf(allowedProtocols);
break;
case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS:
byte[] allowedAuthAlgorithms = (byte[]) value;
configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms);
break;
case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS:
byte[] allowedGroupCiphers = (byte[]) value;
configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers);
break;
case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS:
byte[] allowedPairwiseCiphers = (byte[]) value;
configuration.allowedPairwiseCiphers =
BitSet.valueOf(allowedPairwiseCiphers);
break;
case WifiConfigurationXmlUtil.XML_TAG_SHARED:
configuration.shared = (boolean) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE:
configuration.meteredOverride = (int) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN:
configuration.allowAutojoin = (boolean) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_DELETION_PRIORITY:
configuration.setDeletionPriority((int) value);
break;
case WifiConfigurationXmlUtil.XML_TAG_NUM_REBOOTS_SINCE_LAST_USE:
configuration.numRebootsSinceLastUse = (int) value;
break;
case WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS_LIST:
parseSecurityParamsListFromXml(in, outerTagDepth + 1, configuration);
break;
default:
// should never happen, since other tags are filtered out earlier
throw new XmlPullParserException(
"Unknown value name found: " + tagName);
}
}
clearAnyKnownIssuesInParsedConfiguration(configuration);
return Pair.create(configKeyInData, configuration);
}
/**
* Returns a set of supported tags of <WifiConfiguration> element for all minor versions of
* this major version up to and including the specified minorVersion (only adding tags is
* supported in minor versions, removal or changing the meaning of tags requires bumping
* the major version and reseting the minor to 0).
*
* @param minorVersion minor version number parsed from incoming data.
*/
private static Set<String> getSupportedWifiConfigurationTags(int minorVersion) {
switch (minorVersion) {
case 0:
return WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS;
case 1:
return WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS;
case 2:
return WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS;
case 3:
return WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS;
default:
Log.e(TAG, "Invalid minorVersion: " + minorVersion);
return Collections.<String>emptySet();
}
}
/**
* Populate wepKeys array elements only if they were non-empty in the backup data.
*
* @throws XmlPullParserException if parsing errors occur.
*/
private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys)
throws XmlPullParserException, IOException {
String[] wepKeysInData = (String[]) value;
if (wepKeysInData == null) {
return;
}
if (wepKeysInData.length != wepKeys.length) {
throw new XmlPullParserException(
"Invalid Wep Keys length: " + wepKeysInData.length);
}
for (int i = 0; i < wepKeys.length; i++) {
if (wepKeysInData[i].isEmpty()) {
wepKeys[i] = null;
} else {
wepKeys[i] = wepKeysInData[i];
}
}
}
private static SecurityParams parseSecurityParamsFromXml(
XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException {
SecurityParams params = null;
while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
String[] valueName = new String[1];
Object value = XmlUtil.readCurrentValue(in, valueName);
String tagName = valueName[0];
if (tagName == null) {
throw new XmlPullParserException("Missing value name");
}
switch (tagName) {
case WifiConfigurationXmlUtil.XML_TAG_SECURITY_TYPE:
params = SecurityParams.createSecurityParamsBySecurityType((int) value);
break;
case WifiConfigurationXmlUtil.XML_TAG_SAE_IS_H2E_ONLY_MODE:
if (null == params) throw new XmlPullParserException("Missing security type.");
params.enableSaeH2eOnlyMode((boolean) value);
break;
case WifiConfigurationXmlUtil.XML_TAG_SAE_IS_PK_ONLY_MODE:
if (null == params) throw new XmlPullParserException("Missing security type.");
params.enableSaePkOnlyMode((boolean) value);
break;
case WifiConfigurationXmlUtil.XML_TAG_IS_ADDED_BY_AUTO_UPGRADE:
if (null == params) throw new XmlPullParserException("Missing security type.");
params.setIsAddedByAutoUpgrade((boolean) value);
break;
}
}
return params;
}
/**
* Populate security params list elements only if they were non-empty in the backup data.
*
* @throws XmlPullParserException if parsing errors occur.
*/
private static void parseSecurityParamsListFromXml(
XmlPullParser in, int outerTagDepth,
WifiConfiguration configuration)
throws XmlPullParserException, IOException {
List<SecurityParams> paramsList = new ArrayList<>();
while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
switch (in.getName()) {
case WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS:
SecurityParams params = parseSecurityParamsFromXml(in, outerTagDepth + 1);
if (params != null) {
paramsList.add(params);
}
break;
}
}
if (!paramsList.isEmpty()) {
configuration.setSecurityParams(paramsList);
}
}
private static List<String> parseProxyExclusionListString(
@Nullable String exclusionListString) {
if (exclusionListString == null) {
return Collections.emptyList();
} else {
return Arrays.asList(exclusionListString.toLowerCase(Locale.ROOT).split(","));
}
}
/**
* Parses the IP configuration data elements from the provided XML stream to an
* IpConfiguration object.
*
* @param in XmlPullParser instance pointing to the XML stream.
* @param outerTagDepth depth of the outer tag in the XML document.
* @param minorVersion minor version number parsed from incoming data.
* @return IpConfiguration object if parsing is successful, null otherwise.
*/
private static IpConfiguration parseIpConfigurationFromXml(XmlPullParser in,
int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException {
// First parse *all* of the tags in <IpConfiguration> section
Set<String> supportedTags = getSupportedIpConfigurationTags(minorVersion);
String ipAssignmentString = null;
String linkAddressString = null;
Integer linkPrefixLength = null;
String gatewayAddressString = null;
String[] dnsServerAddressesString = null;
String proxySettingsString = null;
String proxyHost = null;
int proxyPort = -1;
String proxyExclusionList = null;
String proxyPacFile = null;
// Loop through and parse out all the elements from the stream within this section.
while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
String[] valueName = new String[1];
Object value = XmlUtil.readCurrentValue(in, valueName);
String tagName = valueName[0];
if (tagName == null) {
throw new XmlPullParserException("Missing value name");
}
// ignore the tags that are not supported up until the current minor version
if (!supportedTags.contains(tagName)) {
Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <IpConfiguration>"
+ " section, ignoring.");
continue;
}
// note: the below switch case list should contain all tags supported up until the
// highest minor version supported by this parser
// should any tags be added in next minor versions, conditional processing of them
// also needs to be added in the below code (processing into IpConfiguration object)
switch (tagName) {
case IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT:
ipAssignmentString = (String) value;
break;
case IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS:
linkAddressString = (String) value;
break;
case IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH:
linkPrefixLength = (Integer) value;
break;
case IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS:
gatewayAddressString = (String) value;
break;
case IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES:
dnsServerAddressesString = (String[]) value;
break;
case IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS:
proxySettingsString = (String) value;
break;
case IpConfigurationXmlUtil.XML_TAG_PROXY_HOST:
proxyHost = (String) value;
break;
case IpConfigurationXmlUtil.XML_TAG_PROXY_PORT:
proxyPort = (int) value;
break;
case IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST:
proxyExclusionList = (String) value;
break;
case IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE:
proxyPacFile = (String) value;
break;
default:
// should never happen, since other tags are filtered out earlier
throw new XmlPullParserException(
"Unknown value name found: " + valueName[0]);
}
}
// Now process the values into IpConfiguration object
IpConfiguration ipConfiguration = new IpConfiguration();
if (ipAssignmentString == null) {
throw new XmlPullParserException("IpAssignment was missing in IpConfiguration section");
}
IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString);
ipConfiguration.setIpAssignment(ipAssignment);
switch (ipAssignment) {
case STATIC:
StaticIpConfiguration.Builder builder = new StaticIpConfiguration.Builder();
if (linkAddressString != null && linkPrefixLength != null) {
LinkAddress linkAddress = new LinkAddress(
InetAddresses.parseNumericAddress(linkAddressString), linkPrefixLength);
if (linkAddress.getAddress() instanceof Inet4Address) {
builder.setIpAddress(linkAddress);
} else {
Log.w(TAG, "Non-IPv4 address: " + linkAddress);
}
}
if (gatewayAddressString != null) {
InetAddress gateway = InetAddresses.parseNumericAddress(gatewayAddressString);
RouteInfo route = new RouteInfo(null, gateway, null, RouteInfo.RTN_UNICAST);
if (route.isDefaultRoute()
&& route.getDestination().getAddress() instanceof Inet4Address) {
builder.setGateway(gateway);
} else {
Log.w(TAG, "Non-IPv4 default route: " + route);
}
}
if (dnsServerAddressesString != null) {
List<InetAddress> dnsServerAddresses = new ArrayList<>();
for (String dnsServerAddressString : dnsServerAddressesString) {
InetAddress dnsServerAddress =
InetAddresses.parseNumericAddress(dnsServerAddressString);
dnsServerAddresses.add(dnsServerAddress);
}
builder.setDnsServers(dnsServerAddresses);
}
ipConfiguration.setStaticIpConfiguration(builder.build());
break;
case DHCP:
case UNASSIGNED:
break;
default:
throw new XmlPullParserException("Unknown ip assignment type: " + ipAssignment);
}
// Process the proxy settings next
if (proxySettingsString == null) {
throw new XmlPullParserException("ProxySettings was missing in"
+ " IpConfiguration section");
}
ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString);
ipConfiguration.setProxySettings(proxySettings);
switch (proxySettings) {
case STATIC:
if (proxyHost == null) {
throw new XmlPullParserException("ProxyHost was missing in"
+ " IpConfiguration section");
}
if (proxyPort == -1) {
throw new XmlPullParserException("ProxyPort was missing in"
+ " IpConfiguration section");
}
if (proxyExclusionList == null) {
throw new XmlPullParserException("ProxyExclusionList was missing in"
+ " IpConfiguration section");
}
ipConfiguration.setHttpProxy(
ProxyInfo.buildDirectProxy(
proxyHost, proxyPort,
parseProxyExclusionListString(proxyExclusionList)));
break;
case PAC:
if (proxyPacFile == null) {
throw new XmlPullParserException("ProxyPac was missing in"
+ " IpConfiguration section");
}
ipConfiguration.setHttpProxy(
ProxyInfo.buildPacProxy(Uri.parse(proxyPacFile)));
break;
case NONE:
case UNASSIGNED:
break;
default:
throw new XmlPullParserException(
"Unknown proxy settings type: " + proxySettings);
}
return ipConfiguration;
}
/**
* Returns a set of supported tags of <IpConfiguration> element for all minor versions of
* this major version up to and including the specified minorVersion (only adding tags is
* supported in minor versions, removal or changing the meaning of tags requires bumping
* the major version and reseting the minor to 0).
*
* @param minorVersion minor version number parsed from incoming data.
*/
private static Set<String> getSupportedIpConfigurationTags(int minorVersion) {
switch (minorVersion) {
case 0:
case 1:
case 2:
case 3:
return IP_CONFIGURATION_MINOR_V0_V1_V2_V3_SUPPORTED_TAGS;
default:
Log.e(TAG, "Invalid minorVersion: " + minorVersion);
return Collections.<String>emptySet();
}
}
}