• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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