1 /* 2 * Copyright (C) 2014 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.util; 18 19 import android.annotation.Nullable; 20 import android.net.InetAddresses; 21 import android.net.IpConfiguration; 22 import android.net.IpConfiguration.IpAssignment; 23 import android.net.IpConfiguration.ProxySettings; 24 import android.net.IpPrefix; 25 import android.net.LinkAddress; 26 import android.net.ProxyInfo; 27 import android.net.RouteInfo; 28 import android.net.StaticIpConfiguration; 29 import android.net.Uri; 30 import android.util.ArrayMap; 31 import android.util.Log; 32 import android.util.SparseArray; 33 34 import java.io.DataInputStream; 35 import java.io.EOFException; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.net.Inet4Address; 39 import java.net.InetAddress; 40 import java.util.ArrayList; 41 import java.util.Arrays; 42 import java.util.Collections; 43 import java.util.List; 44 import java.util.Locale; 45 46 /** 47 * Note: @hide class copied from com.android.server.net. 48 */ 49 public class IpConfigStore { 50 private static final String TAG = "IpConfigStore"; 51 private static final boolean DBG = false; 52 53 /* IP and proxy configuration keys */ 54 protected static final String ID_KEY = "id"; 55 protected static final String IP_ASSIGNMENT_KEY = "ipAssignment"; 56 protected static final String LINK_ADDRESS_KEY = "linkAddress"; 57 protected static final String GATEWAY_KEY = "gateway"; 58 protected static final String DNS_KEY = "dns"; 59 protected static final String PROXY_SETTINGS_KEY = "proxySettings"; 60 protected static final String PROXY_HOST_KEY = "proxyHost"; 61 protected static final String PROXY_PORT_KEY = "proxyPort"; 62 protected static final String PROXY_PAC_FILE = "proxyPac"; 63 protected static final String EXCLUSION_LIST_KEY = "exclusionList"; 64 protected static final String EOS = "eos"; 65 66 /** 67 * Parses Ip configuration data from the bytestream provided. 68 */ readIpAndProxyConfigurations( InputStream inputStream)69 public static SparseArray<IpConfiguration> readIpAndProxyConfigurations( 70 InputStream inputStream) { 71 ArrayMap<String, IpConfiguration> networks = readIpConfigurations(inputStream); 72 if (networks == null) { 73 return null; 74 } 75 76 SparseArray<IpConfiguration> networksById = new SparseArray<>(); 77 for (int i = 0; i < networks.size(); i++) { 78 int id = Integer.valueOf(networks.keyAt(i)); 79 networksById.put(id, networks.valueAt(i)); 80 } 81 82 return networksById; 83 } 84 85 /** Returns a map of network identity token and {@link IpConfiguration}. */ readIpConfigurations( InputStream inputStream)86 public static ArrayMap<String, IpConfiguration> readIpConfigurations( 87 InputStream inputStream) { 88 ArrayMap<String, IpConfiguration> networks = new ArrayMap<>(); 89 DataInputStream in = null; 90 try { 91 in = new DataInputStream(inputStream); 92 93 int version = in.readInt(); 94 if (version != 3 && version != 2 && version != 1) { 95 loge("Bad version on IP configuration file, ignore read"); 96 return null; 97 } 98 99 while (true) { 100 String uniqueToken = null; 101 // Default is DHCP with no proxy 102 IpAssignment ipAssignment = IpAssignment.DHCP; 103 ProxySettings proxySettings = ProxySettings.NONE; 104 StaticIpConfiguration.Builder staticIPBuilder = new StaticIpConfiguration.Builder(); 105 List<InetAddress> dnsServerAddresses = new ArrayList<>(); 106 String proxyHost = null; 107 String pacFileUrl = null; 108 int proxyPort = -1; 109 String exclusionList = null; 110 String key; 111 112 do { 113 key = in.readUTF(); 114 try { 115 if (ID_KEY.equals(key)) { 116 if (version < 3) { 117 int id = in.readInt(); 118 uniqueToken = String.valueOf(id); 119 } else { 120 uniqueToken = in.readUTF(); 121 } 122 } else if (IP_ASSIGNMENT_KEY.equals(key)) { 123 ipAssignment = IpAssignment.valueOf(in.readUTF()); 124 } else if (key.equals(LINK_ADDRESS_KEY)) { 125 LinkAddress linkAddr = new LinkAddress( 126 InetAddresses.parseNumericAddress(in.readUTF()), in.readInt()); 127 if (linkAddr.getAddress() instanceof Inet4Address) { 128 staticIPBuilder.setIpAddress(linkAddr); 129 } 130 } else if (GATEWAY_KEY.equals(key)) { 131 LinkAddress dest = null; 132 InetAddress gateway = null; 133 if (version == 1) { 134 // only supported default gateways - leave the dest/prefix empty 135 gateway = InetAddresses.parseNumericAddress(in.readUTF()); 136 staticIPBuilder.setGateway(gateway); 137 } else { 138 if (in.readInt() == 1) { 139 dest = new LinkAddress( 140 InetAddresses.parseNumericAddress(in.readUTF()), 141 in.readInt()); 142 } 143 if (in.readInt() == 1) { 144 gateway = InetAddresses.parseNumericAddress(in.readUTF()); 145 } 146 RouteInfo route = new RouteInfo( 147 dest == null ? null : new IpPrefix( 148 dest.getAddress(), dest.getPrefixLength()), 149 gateway, null, RouteInfo.RTN_UNICAST); 150 if (route.isDefaultRoute() 151 && route.getDestination().getAddress() 152 instanceof Inet4Address) { 153 staticIPBuilder.setGateway(gateway); 154 } else { 155 loge("Non-IPv4 default or duplicate route: " + route); 156 } 157 } 158 } else if (DNS_KEY.equals(key)) { 159 dnsServerAddresses.add(InetAddresses.parseNumericAddress(in.readUTF())); 160 } else if (PROXY_SETTINGS_KEY.equals(key)) { 161 proxySettings = ProxySettings.valueOf(in.readUTF()); 162 } else if (PROXY_HOST_KEY.equals(key)) { 163 proxyHost = in.readUTF(); 164 } else if (PROXY_PORT_KEY.equals(key)) { 165 proxyPort = in.readInt(); 166 } else if (PROXY_PAC_FILE.equals(key)) { 167 pacFileUrl = in.readUTF(); 168 } else if (EXCLUSION_LIST_KEY.equals(key)) { 169 exclusionList = in.readUTF(); 170 } else if (EOS.equals(key)) { 171 break; 172 } else { 173 loge("Ignore unknown key " + key + "while reading"); 174 } 175 } catch (IllegalArgumentException e) { 176 loge("Ignore invalid address while reading" + e); 177 } 178 } while (true); 179 180 staticIPBuilder.setDnsServers(dnsServerAddresses); 181 StaticIpConfiguration staticIpConfiguration = staticIPBuilder.build(); 182 if (uniqueToken != null) { 183 IpConfiguration config = new IpConfiguration(); 184 networks.put(uniqueToken, config); 185 186 switch (ipAssignment) { 187 case STATIC: 188 config.setStaticIpConfiguration(staticIpConfiguration); 189 config.setIpAssignment(ipAssignment); 190 break; 191 case DHCP: 192 config.setIpAssignment(ipAssignment); 193 break; 194 case UNASSIGNED: 195 loge("BUG: Found UNASSIGNED IP on file, use DHCP"); 196 config.setIpAssignment(IpAssignment.DHCP); 197 break; 198 default: 199 loge("Ignore invalid ip assignment while reading."); 200 config.setIpAssignment(IpAssignment.UNASSIGNED); 201 break; 202 } 203 204 switch (proxySettings) { 205 case STATIC: 206 ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy( 207 proxyHost, proxyPort, 208 parseProxyExclusionListString(exclusionList)); 209 config.setProxySettings(proxySettings); 210 config.setHttpProxy(proxyInfo); 211 break; 212 case PAC: 213 ProxyInfo proxyPacProperties = 214 ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl)); 215 config.setProxySettings(proxySettings); 216 config.setHttpProxy(proxyPacProperties); 217 break; 218 case NONE: 219 config.setProxySettings(proxySettings); 220 break; 221 case UNASSIGNED: 222 loge("BUG: Found UNASSIGNED proxy on file, use NONE"); 223 config.setProxySettings(ProxySettings.NONE); 224 break; 225 default: 226 loge("Ignore invalid proxy settings while reading"); 227 config.setProxySettings(ProxySettings.UNASSIGNED); 228 break; 229 } 230 } else { 231 if (DBG) log("Missing id while parsing configuration"); 232 } 233 } 234 } catch (EOFException ignore) { 235 } catch (IOException e) { 236 loge("Error parsing configuration: " + e); 237 } finally { 238 if (in != null) { 239 try { 240 in.close(); 241 } catch (Exception e) { } 242 } 243 } 244 245 return networks; 246 } 247 parseProxyExclusionListString( @ullable String exclusionListString)248 private static List<String> parseProxyExclusionListString( 249 @Nullable String exclusionListString) { 250 if (exclusionListString == null) { 251 return Collections.emptyList(); 252 } else { 253 return Arrays.asList(exclusionListString.toLowerCase(Locale.ROOT).split(",")); 254 } 255 } 256 loge(String s)257 protected static void loge(String s) { 258 Log.e(TAG, s, null); 259 } 260 log(String s)261 protected static void log(String s) { 262 Log.d(TAG, s, null); 263 } 264 } 265