From e33a4bb414892435c016486585c26022cafdab68 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Sun, 5 Jun 2016 17:34:15 -0700 Subject: XmlUtil: Move Wifi/IP-Configuration serialization Move the serialization/deserialization of WifiConfiguration & IpConfiguration objects to XmlUtil. This helps us to share this logic between WifiBackupRestore & WifiConfigStore. Changes in the CL: 1. Create |WifiConfigurationXmlUtil| for WifiConfiguration serialization. 2. Create |IpConfigurationXmlUtil| for IpConfiguration serialization. 3. Change the XML structure of backup data to remove nesting of objects. Nesting of objects makes it difficult to deserialize especially when we start adding elements in future revisions. So, move |IpConfiguration| object outside the |WifiConfiguration| object. BUG: 29071904 Change-Id: Id08040bf11e4914638ec9f8d9d27d7983e27e42a TEST: Unit-tests TEST: Manual verification of backup/restore using bmgr commands. --- .../com/android/server/wifi/WifiBackupRestore.java | 426 +++-------------- .../java/com/android/server/wifi/util/XmlUtil.java | 522 ++++++++++++++++++++- 2 files changed, 558 insertions(+), 390 deletions(-) (limited to 'service') diff --git a/service/java/com/android/server/wifi/WifiBackupRestore.java b/service/java/com/android/server/wifi/WifiBackupRestore.java index c37a70c8d..5de29a2c2 100644 --- a/service/java/com/android/server/wifi/WifiBackupRestore.java +++ b/service/java/com/android/server/wifi/WifiBackupRestore.java @@ -17,21 +17,17 @@ package com.android.server.wifi; import android.net.IpConfiguration; -import android.net.LinkAddress; -import android.net.NetworkUtils; -import android.net.ProxyInfo; -import android.net.RouteInfo; -import android.net.StaticIpConfiguration; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; import android.util.Log; import android.util.SparseArray; import android.util.Xml; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FastXmlSerializer; import com.android.server.net.IpConfigStore; 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; @@ -45,17 +41,11 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; -import java.net.Inet4Address; -import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.BitSet; import java.util.List; import java.util.Map; -import static android.net.IpConfiguration.IpAssignment; -import static android.net.IpConfiguration.ProxySettings; - /** * Class used to backup/restore data using the SettingsBackupAgent. * There are 2 symmetric API's exposed here: @@ -79,41 +69,20 @@ public class WifiBackupRestore { private static final int INITIAL_BACKUP_DATA_VERSION = 1; /** - * List of XML tags in the backed up data + * List of XML section header tags in the backed up data */ private static final String XML_TAG_DOCUMENT_HEADER = "WifiBackupData"; private static final String XML_TAG_VERSION = "Version"; - private static final String XML_TAG_SECTION_HEADER_CONFIGURATION_LIST = "ConfigurationList"; - private static final String XML_TAG_SECTION_HEADER_CONFIGURATION = "Configuration"; - private static final String XML_TAG_CONFIGURATION_SSID = "SSID"; - private static final String XML_TAG_CONFIGURATION_BSSID = "BSSID"; - private static final String XML_TAG_CONFIGURATION_CONFIG_KEY = "ConfigKey"; - private static final String XML_TAG_CONFIGURATION_PRE_SHARED_KEY = "PreSharedKey"; - private static final String XML_TAG_CONFIGURATION_WEP_KEYS = "WEPKeys"; - private static final String XML_TAG_CONFIGURATION_WEP_TX_KEY_INDEX = "WEPTxKeyIndex"; - private static final String XML_TAG_CONFIGURATION_HIDDEN_SSID = "HiddenSSID"; - private static final String XML_TAG_CONFIGURATION_ALLOWED_KEY_MGMT = "AllowedKeyMgmt"; - private static final String XML_TAG_CONFIGURATION_ALLOWED_PROTOCOLS = "AllowedProtocols"; - private static final String XML_TAG_CONFIGURATION_ALLOWED_AUTH_ALGOS = "AllowedAuthAlgos"; - private static final String XML_TAG_CONFIGURATION_SHARED = "Shared"; - private static final String XML_TAG_CONFIGURATION_CREATOR_UID = "CreatorUid"; + private static final String XML_TAG_SECTION_HEADER_NETWORK_LIST = "NetworkList"; + private static final String XML_TAG_SECTION_HEADER_NETWORK = "Network"; + private static final String XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION = "WifiConfiguration"; private static final String XML_TAG_SECTION_HEADER_IP_CONFIGURATION = "IpConfiguration"; - private static final String XML_TAG_IP_CONFIGURATION_IP_ASSIGNMENT = "IpAssignment"; - private static final String XML_TAG_IP_CONFIGURATION_LINK_ADDRESS = "LinkAddress"; - private static final String XML_TAG_IP_CONFIGURATION_LINK_PREFIX_LENGTH = "LinkPrefixLength"; - private static final String XML_TAG_IP_CONFIGURATION_GATEWAY_ADDRESS = "GatewayAddress"; - private static final String XML_TAG_IP_CONFIGURATION_DNS_SERVER_ADDRESSES = "DNSServers"; - private static final String XML_TAG_IP_CONFIGURATION_PROXY_SETTINGS = "ProxySettings"; - private static final String XML_TAG_IP_CONFIGURATION_PROXY_HOST = "ProxyHost"; - private static final String XML_TAG_IP_CONFIGURATION_PROXY_PORT = "ProxyPort"; - private static final String XML_TAG_IP_CONFIGURATION_PROXY_PAC_FILE = "ProxyPac"; - private static final String XML_TAG_IP_CONFIGURATION_PROXY_EXCLUSION_LIST = "ProxyExclusionList"; /** * Regex to mask out passwords in backup data dump. */ private static final String PASSWORD_MASK_SEARCH_PATTERN = - "(<.*" + XML_TAG_CONFIGURATION_PRE_SHARED_KEY + ".*>)(.*)(<.*>)"; + "(<.*" + WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY + ".*>)(.*)(<.*>)"; private static final String PASSWORD_MASK_REPLACE_PATTERN = "$1*$3"; /** @@ -152,7 +121,7 @@ public class WifiBackupRestore { XmlUtil.writeNextValue(out, XML_TAG_VERSION, CURRENT_BACKUP_DATA_VERSION); - writeWifiConfigurationsToXml(out, configurations); + writeNetworkConfigurationsToXml(out, configurations); XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER); @@ -174,10 +143,10 @@ public class WifiBackupRestore { /** * Write the list of configurations to the XML stream. */ - private void writeWifiConfigurationsToXml( + private void writeNetworkConfigurationsToXml( XmlSerializer out, List configurations) throws XmlPullParserException, IOException { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_CONFIGURATION_LIST); + XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_LIST); for (WifiConfiguration configuration : configurations) { // We don't want to backup/restore enterprise/passpoint configurations. if (configuration.isEnterprise() || configuration.isPasspoint()) { @@ -185,150 +154,30 @@ public class WifiBackupRestore { continue; } // Write this configuration data now. - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_CONFIGURATION); - writeWifiConfigurationToXml(out, configuration); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_CONFIGURATION); - } - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_CONFIGURATION_LIST); - } - - /** - * Write WepKeys to the XML stream. - * WepKeys array is intialized in WifiConfiguration constructor, but all of the elements - * are null. XmlUtils serialization doesn't handle this array of nulls well . - * So, write null if the keys are not initialized. - */ - private void writeWepKeysToXml(XmlSerializer out, String[] wepKeys) - throws XmlPullParserException, IOException { - if (wepKeys[0] != null) { - XmlUtil.writeNextValue(out, XML_TAG_CONFIGURATION_WEP_KEYS, wepKeys); - } else { - XmlUtil.writeNextValue(out, XML_TAG_CONFIGURATION_WEP_KEYS, null); + XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK); + writeNetworkConfigurationToXml(out, configuration); + XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK); } + XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_LIST); } /** * Write the configuration data elements from the provided Configuration to the XML stream. * Uses XmlUtils to write the values of each element. */ - private void writeWifiConfigurationToXml(XmlSerializer out, WifiConfiguration configuration) + private void writeNetworkConfigurationToXml(XmlSerializer out, WifiConfiguration configuration) throws XmlPullParserException, IOException { - XmlUtil.writeNextValue(out, XML_TAG_CONFIGURATION_CONFIG_KEY, configuration.configKey()); - XmlUtil.writeNextValue(out, XML_TAG_CONFIGURATION_SSID, configuration.SSID); - XmlUtil.writeNextValue(out, XML_TAG_CONFIGURATION_BSSID, configuration.BSSID); - XmlUtil.writeNextValue( - out, XML_TAG_CONFIGURATION_PRE_SHARED_KEY, configuration.preSharedKey); - writeWepKeysToXml(out, configuration.wepKeys); - XmlUtil.writeNextValue( - out, XML_TAG_CONFIGURATION_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex); - XmlUtil.writeNextValue(out, XML_TAG_CONFIGURATION_HIDDEN_SSID, configuration.hiddenSSID); - XmlUtil.writeNextValue( - out, XML_TAG_CONFIGURATION_ALLOWED_KEY_MGMT, - configuration.allowedKeyManagement.toByteArray()); - XmlUtil.writeNextValue( - out, XML_TAG_CONFIGURATION_ALLOWED_PROTOCOLS, - configuration.allowedProtocols.toByteArray()); - XmlUtil.writeNextValue( - out, XML_TAG_CONFIGURATION_ALLOWED_AUTH_ALGOS, - configuration.allowedAuthAlgorithms.toByteArray()); - XmlUtil.writeNextValue(out, XML_TAG_CONFIGURATION_SHARED, configuration.shared); - XmlUtil.writeNextValue(out, XML_TAG_CONFIGURATION_CREATOR_UID, configuration.creatorUid); - + XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); + WifiConfigurationXmlUtil.writeWifiConfigurationToXmlForBackup(out, configuration); + XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); if (configuration.getIpConfiguration() != null) { XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION); - writeIpConfigurationToXml(out, configuration.getIpConfiguration()); + IpConfigurationXmlUtil.writeIpConfigurationToXml( + out, configuration.getIpConfiguration()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION); } } - /** - * Write the static IP configuration data elements to XML stream - */ - private void writeStaticIpConfigurationToXml(XmlSerializer out, - StaticIpConfiguration staticIpConfiguration) - throws XmlPullParserException, IOException { - if (staticIpConfiguration.ipAddress != null) { - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_LINK_ADDRESS, - staticIpConfiguration.ipAddress.getAddress().getHostAddress()); - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_LINK_PREFIX_LENGTH, - staticIpConfiguration.ipAddress.getPrefixLength()); - } else { - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_LINK_ADDRESS, null); - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_LINK_PREFIX_LENGTH, null); - } - if (staticIpConfiguration.gateway != null) { - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_GATEWAY_ADDRESS, - staticIpConfiguration.gateway.getHostAddress()); - } else { - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_GATEWAY_ADDRESS, null); - - } - if (staticIpConfiguration.dnsServers != null) { - // Create a string array of DNS server addresses - String[] dnsServers = new String[staticIpConfiguration.dnsServers.size()]; - int dnsServerIdx = 0; - for (InetAddress inetAddr : staticIpConfiguration.dnsServers) { - dnsServers[dnsServerIdx++] = inetAddr.getHostAddress(); - } - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_DNS_SERVER_ADDRESSES, dnsServers); - } else { - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_DNS_SERVER_ADDRESSES, null); - } - } - - /** - * Write the IP configuration data elements from the provided Configuration to the XML stream. - * Uses XmlUtils to write the values of each element. - */ - private void writeIpConfigurationToXml(XmlSerializer out, IpConfiguration ipConfiguration) - throws XmlPullParserException, IOException { - - // Write IP assignment settings - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_IP_ASSIGNMENT, - ipConfiguration.ipAssignment.toString()); - switch (ipConfiguration.ipAssignment) { - case STATIC: - writeStaticIpConfigurationToXml(out, ipConfiguration.getStaticIpConfiguration()); - break; - default: - break; - } - - // Write proxy settings - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_PROXY_SETTINGS, - ipConfiguration.proxySettings.toString()); - switch (ipConfiguration.proxySettings) { - case STATIC: - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_PROXY_HOST, - ipConfiguration.httpProxy.getHost()); - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_PROXY_PORT, - ipConfiguration.httpProxy.getPort()); - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_PROXY_EXCLUSION_LIST, - ipConfiguration.httpProxy.getExclusionListAsString()); - break; - case PAC: - XmlUtil.writeNextValue( - out, XML_TAG_IP_CONFIGURATION_PROXY_PAC_FILE, - ipConfiguration.httpProxy.getPacFileUrl().toString()); - break; - default: - break; - } - } - /** * Parse out the configurations from the back up data. * @@ -354,13 +203,13 @@ public class WifiBackupRestore { XmlUtil.gotoDocumentStart(in, XML_TAG_DOCUMENT_HEADER); int rootTagDepth = in.getDepth(); - int version = (int) XmlUtil.readNextValue(in, XML_TAG_VERSION); + int version = (int) XmlUtil.readNextValueWithName(in, XML_TAG_VERSION); if (version < INITIAL_BACKUP_DATA_VERSION || version > CURRENT_BACKUP_DATA_VERSION) { Log.e(TAG, "Invalid version of data: " + version); return null; } - return parseWifiConfigurationsFromXml(in, rootTagDepth, version); + return parseNetworkConfigurationsFromXml(in, rootTagDepth, version); } catch (XmlPullParserException e) { Log.e(TAG, "Error parsing the backup data: " + e); } catch (IOException e) { @@ -377,23 +226,22 @@ public class WifiBackupRestore { * @param dataVersion version number parsed from incoming data. * @return List object if parsing is successful, null otherwise. */ - private List parseWifiConfigurationsFromXml( + private List parseNetworkConfigurationsFromXml( XmlPullParser in, int outerTagDepth, int dataVersion) throws XmlPullParserException, IOException { // Find the configuration list section. if (!XmlUtil.gotoNextSection( - in, XML_TAG_SECTION_HEADER_CONFIGURATION_LIST, outerTagDepth)) { - Log.e(TAG, "Error parsing the backup data. Did not find configuration list"); + in, XML_TAG_SECTION_HEADER_NETWORK_LIST, outerTagDepth)) { + Log.e(TAG, "Error parsing the backup data. Did not find network list"); // Malformed XML input, bail out. return null; } // Find all the configurations within the configuration list section. - int confListTagDepth = outerTagDepth + 1; + int networkListTagDepth = outerTagDepth + 1; List configurations = new ArrayList<>(); - while (XmlUtil.gotoNextSection( - in, XML_TAG_SECTION_HEADER_CONFIGURATION, confListTagDepth)) { + while (XmlUtil.gotoNextSection(in, XML_TAG_SECTION_HEADER_NETWORK, networkListTagDepth)) { WifiConfiguration configuration = - parseWifiConfigurationFromXml(in, dataVersion, confListTagDepth); + parseNetworkConfigurationFromXml(in, dataVersion, networkListTagDepth); if (configuration != null) { Log.v(TAG, "Parsed Configuration: " + configuration.configKey()); configurations.add(configuration); @@ -402,21 +250,6 @@ public class WifiBackupRestore { return configurations; } - /** - * Parse WepKeys from the XML stream. - * Populate wepKeys array only if they were present in the backup data. - */ - private void parseWepKeysFromXml(XmlPullParser in, String[] wepKeys) - throws XmlPullParserException, IOException { - String[] wepKeysInData = - (String[]) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_WEP_KEYS); - if (wepKeysInData != null) { - for (int i = 0; i < wepKeys.length; i++) { - wepKeys[i] = wepKeysInData[i]; - } - } - } - /** * Parses the configuration data elements from the provided XML stream to a Configuration. * @@ -425,53 +258,29 @@ public class WifiBackupRestore { * @param dataVersion version number parsed from incoming data. * @return WifiConfiguration object if parsing is successful, null otherwise. */ - private WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in, int dataVersion, + private WifiConfiguration parseNetworkConfigurationFromXml(XmlPullParser in, int dataVersion, int outerTagDepth) throws XmlPullParserException, IOException { - // Any version migration needs to be handled here in future. if (dataVersion == INITIAL_BACKUP_DATA_VERSION) { - WifiConfiguration configuration = new WifiConfiguration(); - String configKeyInData = - (String) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_CONFIG_KEY); - configuration.SSID = - (String) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_SSID); - configuration.BSSID = - (String) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_BSSID); - configuration.preSharedKey = - (String) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_PRE_SHARED_KEY); - parseWepKeysFromXml(in, configuration.wepKeys); - configuration.wepTxKeyIndex = - (int) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_WEP_TX_KEY_INDEX); - configuration.hiddenSSID = - (boolean) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_HIDDEN_SSID); - byte[] allowedKeyMgmt = - (byte[]) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_ALLOWED_KEY_MGMT); - configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); - byte[] allowedProtocols = - (byte[]) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_ALLOWED_PROTOCOLS); - configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); - byte[] allowedAuthAlgorithms = - (byte[]) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_ALLOWED_AUTH_ALGOS); - configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); - configuration.shared = - (boolean) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_SHARED); - configuration.creatorUid = - (int) XmlUtil.readNextValue(in, XML_TAG_CONFIGURATION_CREATOR_UID); - - // We should not have all the data to calculate the configKey. Compare it against the - // configKey stored in the XML data. - String configKeyCalculated = configuration.configKey(); - if (!configKeyInData.equals(configKeyCalculated)) { - Log.e(TAG, "Configuration key does not match. Retrieved: " + configKeyInData - + ", Calculated: " + configKeyCalculated); - return null; + WifiConfiguration configuration = null; + int networkTagDepth = outerTagDepth + 1; + // Retrieve WifiConfiguration object first. + if (XmlUtil.gotoNextSection( + in, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION, networkTagDepth)) { + int configTagDepth = networkTagDepth + 1; + configuration = + WifiConfigurationXmlUtil.parseWifiConfigurationFromXml(in, configTagDepth); + if (configuration == null) { + return null; + } } // Now retrieve any IP configuration info if present. - int confTagDepth = outerTagDepth + 1; if (XmlUtil.gotoNextSection( - in, XML_TAG_SECTION_HEADER_IP_CONFIGURATION, confTagDepth)) { - IpConfiguration ipConfiguration = parseIpConfigurationFromXml(in, dataVersion); + in, XML_TAG_SECTION_HEADER_IP_CONFIGURATION, networkTagDepth)) { + int configTagDepth = networkTagDepth + 1; + IpConfiguration ipConfiguration = + IpConfigurationXmlUtil.parseIpConfigurationFromXml(in, configTagDepth); configuration.setIpConfiguration(ipConfiguration); } return configuration; @@ -479,120 +288,6 @@ public class WifiBackupRestore { return null; } - /** - * Parse out the static IP configuration from the XML stream. - */ - private StaticIpConfiguration parseStaticIpConfigurationFromXml(XmlPullParser in) - throws XmlPullParserException, IOException { - - StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); - String linkAddressString = - (String) XmlUtil.readNextValue(in, XML_TAG_IP_CONFIGURATION_LINK_ADDRESS); - Integer linkPrefixLength = - (Integer) XmlUtil.readNextValue(in, XML_TAG_IP_CONFIGURATION_LINK_PREFIX_LENGTH); - if (linkAddressString != null && linkPrefixLength != null) { - LinkAddress linkAddress = new LinkAddress( - NetworkUtils.numericToInetAddress(linkAddressString), - linkPrefixLength); - if (linkAddress.getAddress() instanceof Inet4Address) { - staticIpConfiguration.ipAddress = linkAddress; - } else { - Log.w(TAG, "Non-IPv4 address: " + linkAddress); - } - } - String gatewayAddressString = - (String) XmlUtil.readNextValue(in, XML_TAG_IP_CONFIGURATION_GATEWAY_ADDRESS); - if (gatewayAddressString != null) { - LinkAddress dest = null; - InetAddress gateway = - NetworkUtils.numericToInetAddress(gatewayAddressString); - RouteInfo route = new RouteInfo(dest, gateway); - if (route.isIPv4Default()) { - staticIpConfiguration.gateway = gateway; - } else { - Log.w(TAG, "Non-IPv4 default route: " + route); - } - } - String[] dnsServerAddressesString = - (String[]) XmlUtil.readNextValue(in, XML_TAG_IP_CONFIGURATION_DNS_SERVER_ADDRESSES); - if (dnsServerAddressesString != null) { - for (String dnsServerAddressString : dnsServerAddressesString) { - InetAddress dnsServerAddress = - NetworkUtils.numericToInetAddress(dnsServerAddressString); - staticIpConfiguration.dnsServers.add(dnsServerAddress); - } - } - return staticIpConfiguration; - } - - /** - * Parses the IP configuration data elements from the provided XML stream to a IpConfiguration. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param dataVersion version number parsed from incoming data. - * @return IpConfiguration object if parsing is successful, null otherwise. - */ - private IpConfiguration parseIpConfigurationFromXml(XmlPullParser in, int dataVersion) - throws XmlPullParserException, IOException { - - // Any version migration needs to be handled here in future. - if (dataVersion == INITIAL_BACKUP_DATA_VERSION) { - IpConfiguration ipConfiguration = new IpConfiguration(); - - // Parse out the IP assignment info first. - String ipAssignmentString = - (String) XmlUtil.readNextValue(in, XML_TAG_IP_CONFIGURATION_IP_ASSIGNMENT); - IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); - ipConfiguration.setIpAssignment(ipAssignment); - switch (ipAssignment) { - case STATIC: - StaticIpConfiguration staticIpConfiguration = - parseStaticIpConfigurationFromXml(in); - ipConfiguration.setStaticIpConfiguration(staticIpConfiguration); - break; - case DHCP: - case UNASSIGNED: - break; - default: - Log.wtf(TAG, "Unknown ip assignment type: " + ipAssignment); - return null; - } - - // Parse out the proxy settings next. - String proxySettingsString = - (String) XmlUtil.readNextValue(in, XML_TAG_IP_CONFIGURATION_PROXY_SETTINGS); - ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); - ipConfiguration.setProxySettings(proxySettings); - switch (proxySettings) { - case STATIC: - String proxyHost = - (String) XmlUtil.readNextValue(in, XML_TAG_IP_CONFIGURATION_PROXY_HOST); - int proxyPort = - (int) XmlUtil.readNextValue(in, XML_TAG_IP_CONFIGURATION_PROXY_PORT); - String proxyExclusionList = - (String) XmlUtil.readNextValue(in, - XML_TAG_IP_CONFIGURATION_PROXY_EXCLUSION_LIST); - ipConfiguration.setHttpProxy( - new ProxyInfo(proxyHost, proxyPort, proxyExclusionList)); - break; - case PAC: - String proxyPacFile = - (String) XmlUtil.readNextValue(in, - XML_TAG_IP_CONFIGURATION_PROXY_PAC_FILE); - ipConfiguration.setHttpProxy(new ProxyInfo(proxyPacFile)); - break; - case NONE: - case UNASSIGNED: - break; - default: - Log.wtf(TAG, "Unknown proxy settings type: " + proxySettings); - return null; - } - return ipConfiguration; - } - return null; - } - /** * Create log dump of the backup data in XML format with the preShared * key masked. @@ -711,7 +406,6 @@ public class WifiBackupRestore { * List of keys to look out for in wpa_supplicant.conf parsing. * These key values are declared in different parts of the wifi codebase today. */ - @VisibleForTesting public static final String SUPPLICANT_KEY_SSID = WifiConfiguration.ssidVarName; public static final String SUPPLICANT_KEY_HIDDEN = WifiConfiguration.hiddenSSIDVarName; public static final String SUPPLICANT_KEY_KEY_MGMT = WifiConfiguration.KeyMgmt.varName; @@ -734,6 +428,22 @@ public class WifiBackupRestore { "(.*" + SUPPLICANT_KEY_PSK + ".*=)(.*)"; private static final String PASSWORD_MASK_REPLACE_PATTERN = "$1*"; + /** + * Create log dump of the backup data in wpa_supplicant.conf format with the preShared + * key masked. + */ + public static String createLogFromBackupData(byte[] data) { + String supplicantConfString; + try { + supplicantConfString = new String(data, StandardCharsets.UTF_8.name()); + supplicantConfString = supplicantConfString.replaceAll( + PASSWORD_MASK_SEARCH_PATTERN, PASSWORD_MASK_REPLACE_PATTERN); + } catch (UnsupportedEncodingException e) { + return ""; + } + return supplicantConfString; + } + /** * Class for capturing a network definition from the wifi supplicant config file. */ @@ -944,21 +654,5 @@ public class WifiBackupRestore { return wifiConfigurations; } } - - /** - * Create log dump of the backup data in wpa_supplicant.conf format with the preShared - * key masked. - */ - public static String createLogFromBackupData(byte[] data) { - String supplicantConfString; - try { - supplicantConfString = new String(data, StandardCharsets.UTF_8.name()); - supplicantConfString = supplicantConfString.replaceAll( - PASSWORD_MASK_SEARCH_PATTERN, PASSWORD_MASK_REPLACE_PATTERN); - } catch (UnsupportedEncodingException e) { - return ""; - } - return supplicantConfString; - } } } diff --git a/service/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java index 9073959e7..214450c6e 100644 --- a/service/java/com/android/server/wifi/util/XmlUtil.java +++ b/service/java/com/android/server/wifi/util/XmlUtil.java @@ -16,6 +16,17 @@ package com.android.server.wifi.util; +import android.net.IpConfiguration; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkAddress; +import android.net.NetworkUtils; +import android.net.ProxyInfo; +import android.net.RouteInfo; +import android.net.StaticIpConfiguration; +import android.net.wifi.WifiConfiguration; +import android.util.Log; + import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; @@ -23,11 +34,13 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.util.BitSet; /** * Utils for manipulating XML data. This is essentially a wrapper over XmlUtils provided by core. * The utility provides methods to write/parse section headers and write/parse values. - * * This utility is designed for formatting the XML into the following format: * *
@@ -46,11 +59,29 @@ public class XmlUtil { private static final String TAG = "WifiXmlUtil"; /** - * Move the XML stream to the start of the next tag or the end of document. + * Ensure that the XML stream is at a start tag or the end of document. + * + * @throws {XmlPullParserException}, if parsing errors occur. */ - private static void gotoNextElement(XmlPullParser in) + private static void gotoStartTag(XmlPullParser in) throws XmlPullParserException, IOException { - XmlUtils.nextElement(in); + int type = in.getEventType(); + while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { + type = in.next(); + } + } + + /** + * Ensure that the XML stream is at an end tag or the end of document. + * + * @throws {XmlPullParserException}, if parsing errors occur. + */ + private static void gotoEndTag(XmlPullParser in) + throws XmlPullParserException, IOException { + int type = in.getEventType(); + while (type != XmlPullParser.END_TAG && type != XmlPullParser.END_DOCUMENT) { + type = in.next(); + } } /** @@ -58,6 +89,7 @@ public class XmlUtil { * * @param in XmlPullParser instance pointing to the XML stream. * @param headerName expected name for the start tag. + * @throws {XmlPullParserException}, if parsing errors occur. */ public static void gotoDocumentStart(XmlPullParser in, String headerName) throws XmlPullParserException, IOException { @@ -65,13 +97,14 @@ public class XmlUtil { } /** - * Move the XML stream to the next section header. The provided outerdepth is used to find - * sub sections within the provided depth. + * Move the XML stream to the next section header. The provided outerDepth is used to find + * sub sections within that depth. * * @param in XmlPullParser instance pointing to the XML stream. * @param headerName expected name for the start tag. * @param outerDepth Find section within this depth. * @return {@code true} if a start tag with the provided name is found, {@code false} otherwise + * @throws {XmlPullParserException}, if parsing errors occur. */ public static boolean gotoNextSection(XmlPullParser in, String headerName, int outerDepth) throws XmlPullParserException, IOException { @@ -83,9 +116,50 @@ public class XmlUtil { return false; } + /** + * Checks if the stream is at the end of a section of values. This moves the stream to next tag + * and checks if it finds an end tag at the specified depth. + * + * @param in XmlPullParser instance pointing to the XML stream. + * @param sectionDepth depth of the start tag of this section. Used to match the end tag. + * @return {@code true} if a end tag at the provided depth is found, {@code false} otherwise + * @throws {XmlPullParserException}, if parsing errors occur. + */ + public static boolean isNextSectionEnd(XmlPullParser in, int sectionDepth) + throws XmlPullParserException, IOException { + if (in.nextTag() == XmlPullParser.END_TAG && in.getDepth() == sectionDepth) { + return true; + } else { + return false; + } + } + + /** + * Read the current value in the XML stream using core XmlUtils and stores the retrieved + * value name in the string provided. This method reads the value contained in current start + * tag. + * Note: Because there could be genuine null values being read from the XML, this method raises + * an exception to indicate errors. + * + * @param in XmlPullParser instance pointing to the XML stream. + * @param valueName An array of one string, used to return the name attribute + * of the value's tag. + * @return value retrieved from the XML stream. + * @throws {XmlPullParserException}, if parsing errors occur. + */ + public static Object readCurrentValue(XmlPullParser in, String[] valueName) + throws XmlPullParserException, IOException { + Object value = XmlUtils.readValueXml(in, valueName); + // XmlUtils.readValue does not always move the stream to the end of the tag. So, move + // it to the end tag before returning from here. + gotoEndTag(in); + return value; + } + /** * Read the next value in the XML stream using core XmlUtils and ensure that it matches the - * provided name. + * provided name. This method moves the stream to the next start tag and reads the value + * contained in it. * Note: Because there could be genuine null values being read from the XML, this method raises * an exception to indicate errors. * @@ -94,23 +168,16 @@ public class XmlUtil { * @throws {XmlPullParserException}, if the value read does not match |expectedName|, * or if parsing errors occur. */ - public static Object readNextValue(XmlPullParser in, String expectedName) + public static Object readNextValueWithName(XmlPullParser in, String expectedName) throws XmlPullParserException, IOException { - String[] names = new String[1]; - names[0] = new String(); - gotoNextElement(in); - Object value = XmlUtils.readValueXml(in, names); - if (names[0].equals(expectedName)) { - // XmlUtils.readValue does not always move the stream to the end of the tag. So, move - // it to the end before returning from here. - while (in.getEventType() != XmlPullParser.END_DOCUMENT - && in.getEventType() != XmlPullParser.END_TAG) { - in.next(); - } + String[] valueName = new String[1]; + XmlUtils.nextElement(in); + Object value = readCurrentValue(in, valueName); + if (valueName[0].equals(expectedName)) { return value; } throw new XmlPullParserException( - "Value not found. Expected: " + expectedName + ", but got: " + names[0]); + "Value not found. Expected: " + expectedName + ", but got: " + valueName[0]); } /** @@ -120,7 +187,7 @@ public class XmlUtil { * @param headerName name for the start tag. */ public static void writeDocumentStart(XmlSerializer out, String headerName) - throws XmlPullParserException, IOException { + throws IOException { out.startDocument(null, true); out.startTag(null, headerName); } @@ -132,7 +199,7 @@ public class XmlUtil { * @param headerName name for the end tag. */ public static void writeDocumentEnd(XmlSerializer out, String headerName) - throws XmlPullParserException, IOException { + throws IOException { out.endTag(null, headerName); out.endDocument(); } @@ -144,7 +211,7 @@ public class XmlUtil { * @param headerName name for the start tag. */ public static void writeNextSectionStart(XmlSerializer out, String headerName) - throws XmlPullParserException, IOException { + throws IOException { out.startTag(null, headerName); } @@ -155,7 +222,7 @@ public class XmlUtil { * @param headerName name for the end tag. */ public static void writeNextSectionEnd(XmlSerializer out, String headerName) - throws XmlPullParserException, IOException { + throws IOException { out.endTag(null, headerName); } @@ -170,5 +237,412 @@ public class XmlUtil { throws XmlPullParserException, IOException { XmlUtils.writeValueXml(value, name, out); } + + /** + * Utility class to serialize and deseriaize WifConfiguration object to XML & vice versa. + * This is used by both #com.android.server.wifi.WifiConfigStore & + * #com.android.server.wifi.WifiBackupRestore modules. + * The |writeConfigurationToXml| has 2 versions, one for backup and one for config store. + * There is only 1 version of |parseXmlToConfiguration| for both backup & config store. + * The parse method is written so that any element added/deleted in future revisions can + * be easily handled. + */ + public static class WifiConfigurationXmlUtil { + /** + * List of XML tags corresponding to WifiConfiguration object elements. + */ + public static final String XML_TAG_SSID = "SSID"; + public static final String XML_TAG_BSSID = "BSSID"; + public static final String XML_TAG_CONFIG_KEY = "ConfigKey"; + public static final String XML_TAG_PRE_SHARED_KEY = "PreSharedKey"; + public static final String XML_TAG_WEP_KEYS = "WEPKeys"; + public static final String XML_TAG_WEP_TX_KEY_INDEX = "WEPTxKeyIndex"; + public static final String XML_TAG_HIDDEN_SSID = "HiddenSSID"; + public static final String XML_TAG_ALLOWED_KEY_MGMT = "AllowedKeyMgmt"; + public static final String XML_TAG_ALLOWED_PROTOCOLS = "AllowedProtocols"; + public static final String XML_TAG_ALLOWED_AUTH_ALGOS = "AllowedAuthAlgos"; + public static final String XML_TAG_SHARED = "Shared"; + public static final String XML_TAG_CREATOR_UID = "CreatorUid"; + + /** + * Write WepKeys to the XML stream. + * WepKeys array is intialized in WifiConfiguration constructor, but all of the elements + * are null. XmlUtils serialization doesn't handle this array of nulls well . + * So, write null if the keys are not initialized. + */ + private static void writeWepKeysToXml(XmlSerializer out, String[] wepKeys) + throws XmlPullParserException, IOException { + if (wepKeys[0] != null) { + XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeys); + } else { + XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, null); + } + } + + /** + * Write the Configuration data elements that are common for backup & config store to the + * XML stream. + * + * @param out XmlSerializer instance pointing to the XML stream. + * @param configuration WifiConfiguration object to be serialized. + */ + public static void writeCommonWifiConfigurationElementsToXml(XmlSerializer out, + WifiConfiguration configuration) + throws XmlPullParserException, IOException { + XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.configKey()); + XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID); + XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID); + XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, configuration.preSharedKey); + writeWepKeysToXml(out, configuration.wepKeys); + XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex); + XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID); + XmlUtil.writeNextValue( + out, XML_TAG_ALLOWED_KEY_MGMT, + configuration.allowedKeyManagement.toByteArray()); + XmlUtil.writeNextValue( + out, XML_TAG_ALLOWED_PROTOCOLS, + configuration.allowedProtocols.toByteArray()); + XmlUtil.writeNextValue( + out, XML_TAG_ALLOWED_AUTH_ALGOS, + configuration.allowedAuthAlgorithms.toByteArray()); + XmlUtil.writeNextValue(out, XML_TAG_SHARED, configuration.shared); + XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, configuration.creatorUid); + } + + /** + * Write the Configuration data elements for backup from the provided Configuration to the + * XML stream. + * Note: This is a subset of the elements serialized for config store. + * + * @param out XmlSerializer instance pointing to the XML stream. + * @param configuration WifiConfiguration object to be serialized. + */ + public static void writeWifiConfigurationToXmlForBackup(XmlSerializer out, + WifiConfiguration configuration) + throws XmlPullParserException, IOException { + writeCommonWifiConfigurationElementsToXml(out, configuration); + } + + /** + * Write the Configuration data elements for config store from the provided Configuration + * to the XML stream. + */ + public static void writeWifiConfigurationToXmlForConfigStore(XmlSerializer out, + WifiConfiguration configuration) + throws XmlPullParserException, IOException { + writeCommonWifiConfigurationElementsToXml(out, configuration); + // TODO: Will need to add more elements which needs to be persisted. + } + + /** + * Populate wepKeys array only if they were non-null in the backup data. + */ + private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) + throws XmlPullParserException, IOException { + String[] wepKeysInData = (String[]) value; + if (wepKeysInData != null) { + for (int i = 0; i < wepKeys.length; i++) { + wepKeys[i] = wepKeysInData[i]; + } + } + } + + /** + * Parses the configuration data elements from the provided XML stream to a Configuration. + * Note: This is used for parsing both backup data and config store data. Looping through + * the tags make it easy to add or remove elements in the future versions if needed. + * + * @param in XmlPullParser instance pointing to the XML stream. + * @param outerTagDepth depth of the outer tag in the XML document. + * @return WifiConfiguration object if parsing is successful, null otherwise. + */ + public static WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in, + int outerTagDepth) + throws XmlPullParserException, IOException { + WifiConfiguration configuration = new WifiConfiguration(); + String configKeyInData = 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); + if (valueName[0] == null) { + Log.e(TAG, "Missing value name"); + return null; + } + switch (valueName[0]) { + case XML_TAG_CONFIG_KEY: + configKeyInData = (String) value; + break; + case XML_TAG_SSID: + configuration.SSID = (String) value; + break; + case XML_TAG_BSSID: + configuration.BSSID = (String) value; + break; + case XML_TAG_PRE_SHARED_KEY: + configuration.preSharedKey = (String) value; + break; + case XML_TAG_WEP_KEYS: + populateWepKeysFromXmlValue(value, configuration.wepKeys); + break; + case XML_TAG_WEP_TX_KEY_INDEX: + configuration.wepTxKeyIndex = (int) value; + break; + case XML_TAG_HIDDEN_SSID: + configuration.hiddenSSID = (boolean) value; + break; + case XML_TAG_ALLOWED_KEY_MGMT: + byte[] allowedKeyMgmt = (byte[]) value; + configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); + break; + case XML_TAG_ALLOWED_PROTOCOLS: + byte[] allowedProtocols = (byte[]) value; + configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); + break; + case XML_TAG_ALLOWED_AUTH_ALGOS: + byte[] allowedAuthAlgorithms = (byte[]) value; + configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); + break; + case XML_TAG_SHARED: + configuration.shared = (boolean) value; + break; + case XML_TAG_CREATOR_UID: + configuration.creatorUid = (int) value; + break; + default: + Log.e(TAG, "Unknown value name found: " + valueName[0]); + return null; + } + } + // We should now have all the data to calculate the configKey. Compare it against the + // configKey stored in the XML data. + String configKeyCalculated = configuration.configKey(); + if (configKeyInData == null || !configKeyInData.equals(configKeyCalculated)) { + Log.e(TAG, "Configuration key does not match. Retrieved: " + configKeyInData + + ", Calculated: " + configKeyCalculated); + return null; + } + return configuration; + } + } + + /** + * Utility class to serialize and deseriaize IpConfiguration object to XML & vice versa. + * This is used by both #com.android.server.wifi.WifiConfigStore & + * #com.android.server.wifi.WifiBackupRestore modules. + */ + public static class IpConfigurationXmlUtil { + + /** + * List of XML tags corresponding to IpConfiguration object elements. + */ + public static final String XML_TAG_IP_ASSIGNMENT = "IpAssignment"; + public static final String XML_TAG_LINK_ADDRESS = "LinkAddress"; + public static final String XML_TAG_LINK_PREFIX_LENGTH = "LinkPrefixLength"; + public static final String XML_TAG_GATEWAY_ADDRESS = "GatewayAddress"; + public static final String XML_TAG_DNS_SERVER_ADDRESSES = "DNSServers"; + public static final String XML_TAG_PROXY_SETTINGS = "ProxySettings"; + public static final String XML_TAG_PROXY_HOST = "ProxyHost"; + public static final String XML_TAG_PROXY_PORT = "ProxyPort"; + public static final String XML_TAG_PROXY_PAC_FILE = "ProxyPac"; + public static final String XML_TAG_PROXY_EXCLUSION_LIST = "ProxyExclusionList"; + + /** + * Write the static IP configuration data elements to XML stream. + */ + private static void writeStaticIpConfigurationToXml(XmlSerializer out, + StaticIpConfiguration staticIpConfiguration) + throws XmlPullParserException, IOException { + if (staticIpConfiguration.ipAddress != null) { + XmlUtil.writeNextValue( + out, XML_TAG_LINK_ADDRESS, + staticIpConfiguration.ipAddress.getAddress().getHostAddress()); + XmlUtil.writeNextValue( + out, XML_TAG_LINK_PREFIX_LENGTH, + staticIpConfiguration.ipAddress.getPrefixLength()); + } else { + XmlUtil.writeNextValue( + out, XML_TAG_LINK_ADDRESS, null); + XmlUtil.writeNextValue( + out, XML_TAG_LINK_PREFIX_LENGTH, null); + } + if (staticIpConfiguration.gateway != null) { + XmlUtil.writeNextValue( + out, XML_TAG_GATEWAY_ADDRESS, + staticIpConfiguration.gateway.getHostAddress()); + } else { + XmlUtil.writeNextValue( + out, XML_TAG_GATEWAY_ADDRESS, null); + + } + if (staticIpConfiguration.dnsServers != null) { + // Create a string array of DNS server addresses + String[] dnsServers = new String[staticIpConfiguration.dnsServers.size()]; + int dnsServerIdx = 0; + for (InetAddress inetAddr : staticIpConfiguration.dnsServers) { + dnsServers[dnsServerIdx++] = inetAddr.getHostAddress(); + } + XmlUtil.writeNextValue( + out, XML_TAG_DNS_SERVER_ADDRESSES, dnsServers); + } else { + XmlUtil.writeNextValue( + out, XML_TAG_DNS_SERVER_ADDRESSES, null); + } + } + + /** + * Write the IP configuration data elements from the provided Configuration to the XML + * stream. + */ + public static void writeIpConfigurationToXml(XmlSerializer out, + IpConfiguration ipConfiguration) + throws XmlPullParserException, IOException { + // Write IP assignment settings + XmlUtil.writeNextValue(out, XML_TAG_IP_ASSIGNMENT, + ipConfiguration.ipAssignment.toString()); + switch (ipConfiguration.ipAssignment) { + case STATIC: + writeStaticIpConfigurationToXml( + out, ipConfiguration.getStaticIpConfiguration()); + break; + default: + break; + } + + // Write proxy settings + XmlUtil.writeNextValue( + out, XML_TAG_PROXY_SETTINGS, + ipConfiguration.proxySettings.toString()); + switch (ipConfiguration.proxySettings) { + case STATIC: + XmlUtil.writeNextValue( + out, XML_TAG_PROXY_HOST, + ipConfiguration.httpProxy.getHost()); + XmlUtil.writeNextValue( + out, XML_TAG_PROXY_PORT, + ipConfiguration.httpProxy.getPort()); + XmlUtil.writeNextValue( + out, XML_TAG_PROXY_EXCLUSION_LIST, + ipConfiguration.httpProxy.getExclusionListAsString()); + break; + case PAC: + XmlUtil.writeNextValue( + out, XML_TAG_PROXY_PAC_FILE, + ipConfiguration.httpProxy.getPacFileUrl().toString()); + break; + default: + break; + } + } + + /** + * Parse out the static IP configuration from the XML stream. + */ + private static StaticIpConfiguration parseStaticIpConfigurationFromXml(XmlPullParser in) + throws XmlPullParserException, IOException { + StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); + + String linkAddressString = + (String) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_ADDRESS); + Integer linkPrefixLength = + (Integer) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_PREFIX_LENGTH); + if (linkAddressString != null && linkPrefixLength != null) { + LinkAddress linkAddress = new LinkAddress( + NetworkUtils.numericToInetAddress(linkAddressString), + linkPrefixLength); + if (linkAddress.getAddress() instanceof Inet4Address) { + staticIpConfiguration.ipAddress = linkAddress; + } else { + Log.w(TAG, "Non-IPv4 address: " + linkAddress); + } + } + String gatewayAddressString = + (String) XmlUtil.readNextValueWithName(in, XML_TAG_GATEWAY_ADDRESS); + if (gatewayAddressString != null) { + LinkAddress dest = null; + InetAddress gateway = + NetworkUtils.numericToInetAddress(gatewayAddressString); + RouteInfo route = new RouteInfo(dest, gateway); + if (route.isIPv4Default()) { + staticIpConfiguration.gateway = gateway; + } else { + Log.w(TAG, "Non-IPv4 default route: " + route); + } + } + String[] dnsServerAddressesString = + (String[]) XmlUtil.readNextValueWithName(in, XML_TAG_DNS_SERVER_ADDRESSES); + if (dnsServerAddressesString != null) { + for (String dnsServerAddressString : dnsServerAddressesString) { + InetAddress dnsServerAddress = + NetworkUtils.numericToInetAddress(dnsServerAddressString); + staticIpConfiguration.dnsServers.add(dnsServerAddress); + } + } + return staticIpConfiguration; + } + + /** + * Parses the IP configuration data elements from the provided XML stream to a + * IpConfiguration. + * + * @param in XmlPullParser instance pointing to the XML stream. + * @param outerTagDepth depth of the outer tag in the XML document. + * @return IpConfiguration object if parsing is successful, null otherwise. + */ + public static IpConfiguration parseIpConfigurationFromXml(XmlPullParser in, + int outerTagDepth) + throws XmlPullParserException, IOException { + IpConfiguration ipConfiguration = new IpConfiguration(); + + // Parse out the IP assignment info first. + String ipAssignmentString = + (String) XmlUtil.readNextValueWithName(in, XML_TAG_IP_ASSIGNMENT); + IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); + ipConfiguration.setIpAssignment(ipAssignment); + switch (ipAssignment) { + case STATIC: + ipConfiguration.setStaticIpConfiguration(parseStaticIpConfigurationFromXml(in)); + break; + case DHCP: + case UNASSIGNED: + break; + default: + Log.wtf(TAG, "Unknown ip assignment type: " + ipAssignment); + return null; + } + + // Parse out the proxy settings next. + String proxySettingsString = + (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_SETTINGS); + ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); + ipConfiguration.setProxySettings(proxySettings); + switch (proxySettings) { + case STATIC: + String proxyHost = + (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_HOST); + int proxyPort = + (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PORT); + String proxyExclusionList = + (String) XmlUtil.readNextValueWithName( + in, XML_TAG_PROXY_EXCLUSION_LIST); + ipConfiguration.setHttpProxy( + new ProxyInfo(proxyHost, proxyPort, proxyExclusionList)); + break; + case PAC: + String proxyPacFile = + (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PAC_FILE); + ipConfiguration.setHttpProxy(new ProxyInfo(proxyPacFile)); + break; + case NONE: + case UNASSIGNED: + break; + default: + Log.wtf(TAG, "Unknown proxy settings type: " + proxySettings); + return null; + } + return ipConfiguration; + } + } } -- cgit v1.2.3