IpConfigStore.java revision 00a0fd650b7a31dffb88c229242bb04fa0b487a4
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
17package com.android.server.net;
18
19import android.net.IpConfiguration;
20import android.net.IpConfiguration.IpAssignment;
21import android.net.IpConfiguration.ProxySettings;
22import android.net.LinkAddress;
23import android.net.LinkProperties;
24import android.net.NetworkUtils;
25import android.net.ProxyInfo;
26import android.net.RouteInfo;
27import android.os.Handler;
28import android.os.HandlerThread;
29import android.text.TextUtils;
30import android.util.Log;
31import android.util.SparseArray;
32
33import com.android.server.net.DelayedDiskWrite;
34
35import java.io.BufferedInputStream;
36import java.io.BufferedOutputStream;
37import java.io.DataInputStream;
38import java.io.DataOutputStream;
39import java.io.EOFException;
40import java.io.FileInputStream;
41import java.io.FileOutputStream;
42import java.io.IOException;
43import java.net.InetAddress;
44import java.util.Map;
45
46public class IpConfigStore {
47    private static final String TAG = "IpConfigStore";
48    private static final boolean DBG = true;
49
50    protected final DelayedDiskWrite mWriter;
51
52    /* IP and proxy configuration keys */
53    protected static final String ID_KEY = "id";
54    protected static final String IP_ASSIGNMENT_KEY = "ipAssignment";
55    protected static final String LINK_ADDRESS_KEY = "linkAddress";
56    protected static final String GATEWAY_KEY = "gateway";
57    protected static final String DNS_KEY = "dns";
58    protected static final String PROXY_SETTINGS_KEY = "proxySettings";
59    protected static final String PROXY_HOST_KEY = "proxyHost";
60    protected static final String PROXY_PORT_KEY = "proxyPort";
61    protected static final String PROXY_PAC_FILE = "proxyPac";
62    protected static final String EXCLUSION_LIST_KEY = "exclusionList";
63    protected static final String EOS = "eos";
64
65    protected static final int IPCONFIG_FILE_VERSION = 2;
66
67    public IpConfigStore() {
68        mWriter = new DelayedDiskWrite();
69    }
70
71    private boolean writeConfig(DataOutputStream out, int configKey,
72                                  IpConfiguration config) throws IOException {
73        boolean written = false;
74
75        try {
76            LinkProperties linkProperties = config.linkProperties;
77            switch (config.ipAssignment) {
78                case STATIC:
79                    out.writeUTF(IP_ASSIGNMENT_KEY);
80                    out.writeUTF(config.ipAssignment.toString());
81                    for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) {
82                        out.writeUTF(LINK_ADDRESS_KEY);
83                        out.writeUTF(linkAddr.getAddress().getHostAddress());
84                        out.writeInt(linkAddr.getPrefixLength());
85                    }
86                    for (RouteInfo route : linkProperties.getRoutes()) {
87                        out.writeUTF(GATEWAY_KEY);
88                        LinkAddress dest = route.getDestination();
89                        if (dest != null) {
90                            out.writeInt(1);
91                            out.writeUTF(dest.getAddress().getHostAddress());
92                            out.writeInt(dest.getPrefixLength());
93                        } else {
94                            out.writeInt(0);
95                        }
96                        if (route.getGateway() != null) {
97                            out.writeInt(1);
98                            out.writeUTF(route.getGateway().getHostAddress());
99                        } else {
100                            out.writeInt(0);
101                        }
102                    }
103                    for (InetAddress inetAddr : linkProperties.getDnses()) {
104                        out.writeUTF(DNS_KEY);
105                        out.writeUTF(inetAddr.getHostAddress());
106                    }
107                    written = true;
108                    break;
109                case DHCP:
110                    out.writeUTF(IP_ASSIGNMENT_KEY);
111                    out.writeUTF(config.ipAssignment.toString());
112                    written = true;
113                    break;
114                case UNASSIGNED:
115                /* Ignore */
116                    break;
117                default:
118                    loge("Ignore invalid ip assignment while writing");
119                    break;
120            }
121
122            switch (config.proxySettings) {
123                case STATIC:
124                    ProxyInfo proxyProperties = linkProperties.getHttpProxy();
125                    String exclusionList = proxyProperties.getExclusionListAsString();
126                    out.writeUTF(PROXY_SETTINGS_KEY);
127                    out.writeUTF(config.proxySettings.toString());
128                    out.writeUTF(PROXY_HOST_KEY);
129                    out.writeUTF(proxyProperties.getHost());
130                    out.writeUTF(PROXY_PORT_KEY);
131                    out.writeInt(proxyProperties.getPort());
132                    out.writeUTF(EXCLUSION_LIST_KEY);
133                    out.writeUTF(exclusionList);
134                    written = true;
135                    break;
136                case PAC:
137                    ProxyInfo proxyPacProperties = linkProperties.getHttpProxy();
138                    out.writeUTF(PROXY_SETTINGS_KEY);
139                    out.writeUTF(config.proxySettings.toString());
140                    out.writeUTF(PROXY_PAC_FILE);
141                    out.writeUTF(proxyPacProperties.getPacFileUrl().toString());
142                    written = true;
143                    break;
144                case NONE:
145                    out.writeUTF(PROXY_SETTINGS_KEY);
146                    out.writeUTF(config.proxySettings.toString());
147                    written = true;
148                    break;
149                case UNASSIGNED:
150                    /* Ignore */
151                        break;
152                    default:
153                        loge("Ignore invalid proxy settings while writing");
154                        break;
155            }
156
157            if (written) {
158                out.writeUTF(ID_KEY);
159                out.writeInt(configKey);
160            }
161        } catch (NullPointerException e) {
162            loge("Failure in writing " + config.linkProperties + e);
163        }
164        out.writeUTF(EOS);
165
166        return written;
167    }
168
169    public void writeIpAndProxyConfigurations(String filePath,
170                                              final SparseArray<IpConfiguration> networks) {
171        mWriter.write(filePath, new DelayedDiskWrite.Writer() {
172            public void onWriteCalled(DataOutputStream out) throws IOException{
173                out.writeInt(IPCONFIG_FILE_VERSION);
174                for(int i = 0; i < networks.size(); i++) {
175                    writeConfig(out, networks.keyAt(i), networks.valueAt(i));
176                }
177            }
178        });
179    }
180
181    public SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
182        SparseArray<IpConfiguration> networks = new SparseArray<IpConfiguration>();
183
184        DataInputStream in = null;
185        try {
186            in = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
187
188            int version = in.readInt();
189            if (version != 2 && version != 1) {
190                loge("Bad version on IP configuration file, ignore read");
191                return null;
192            }
193
194            while (true) {
195                int id = -1;
196                // Default is DHCP with no proxy
197                IpAssignment ipAssignment = IpAssignment.DHCP;
198                ProxySettings proxySettings = ProxySettings.NONE;
199                LinkProperties linkProperties = new LinkProperties();
200                String proxyHost = null;
201                String pacFileUrl = null;
202                int proxyPort = -1;
203                String exclusionList = null;
204                String key;
205
206                do {
207                    key = in.readUTF();
208                    try {
209                        if (key.equals(ID_KEY)) {
210                            id = in.readInt();
211                        } else if (key.equals(IP_ASSIGNMENT_KEY)) {
212                            ipAssignment = IpAssignment.valueOf(in.readUTF());
213                        } else if (key.equals(LINK_ADDRESS_KEY)) {
214                            LinkAddress linkAddr = new LinkAddress(
215                                    NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
216                            linkProperties.addLinkAddress(linkAddr);
217                        } else if (key.equals(GATEWAY_KEY)) {
218                            LinkAddress dest = null;
219                            InetAddress gateway = null;
220                            if (version == 1) {
221                                // only supported default gateways - leave the dest/prefix empty
222                                gateway = NetworkUtils.numericToInetAddress(in.readUTF());
223                            } else {
224                                if (in.readInt() == 1) {
225                                    dest = new LinkAddress(
226                                            NetworkUtils.numericToInetAddress(in.readUTF()),
227                                            in.readInt());
228                                }
229                                if (in.readInt() == 1) {
230                                    gateway = NetworkUtils.numericToInetAddress(in.readUTF());
231                                }
232                            }
233                            linkProperties.addRoute(new RouteInfo(dest, gateway));
234                        } else if (key.equals(DNS_KEY)) {
235                            linkProperties.addDns(
236                                    NetworkUtils.numericToInetAddress(in.readUTF()));
237                        } else if (key.equals(PROXY_SETTINGS_KEY)) {
238                            proxySettings = ProxySettings.valueOf(in.readUTF());
239                        } else if (key.equals(PROXY_HOST_KEY)) {
240                            proxyHost = in.readUTF();
241                        } else if (key.equals(PROXY_PORT_KEY)) {
242                            proxyPort = in.readInt();
243                        } else if (key.equals(PROXY_PAC_FILE)) {
244                            pacFileUrl = in.readUTF();
245                        } else if (key.equals(EXCLUSION_LIST_KEY)) {
246                            exclusionList = in.readUTF();
247                        } else if (key.equals(EOS)) {
248                            break;
249                        } else {
250                            loge("Ignore unknown key " + key + "while reading");
251                        }
252                    } catch (IllegalArgumentException e) {
253                        loge("Ignore invalid address while reading" + e);
254                    }
255                } while (true);
256
257                if (id != -1) {
258                    IpConfiguration config = new IpConfiguration();
259                    networks.put(id, config);
260
261                    config.linkProperties = linkProperties;
262                    switch (ipAssignment) {
263                        case STATIC:
264                        case DHCP:
265                            config.ipAssignment = ipAssignment;
266                            break;
267                        case UNASSIGNED:
268                            loge("BUG: Found UNASSIGNED IP on file, use DHCP");
269                            config.ipAssignment = IpAssignment.DHCP;
270                            break;
271                        default:
272                            loge("Ignore invalid ip assignment while reading.");
273                            config.ipAssignment = IpAssignment.UNASSIGNED;
274                            break;
275                    }
276
277                    switch (proxySettings) {
278                        case STATIC:
279                            config.proxySettings = proxySettings;
280                            ProxyInfo ProxyInfo =
281                                    new ProxyInfo(proxyHost, proxyPort, exclusionList);
282                            linkProperties.setHttpProxy(ProxyInfo);
283                            break;
284                        case PAC:
285                            config.proxySettings = proxySettings;
286                            ProxyInfo proxyPacProperties =
287                                    new ProxyInfo(pacFileUrl);
288                            linkProperties.setHttpProxy(proxyPacProperties);
289                            break;
290                        case NONE:
291                            config.proxySettings = proxySettings;
292                            break;
293                        case UNASSIGNED:
294                            loge("BUG: Found UNASSIGNED proxy on file, use NONE");
295                            config.proxySettings = ProxySettings.NONE;
296                            break;
297                        default:
298                            loge("Ignore invalid proxy settings while reading");
299                            config.proxySettings = ProxySettings.UNASSIGNED;
300                            break;
301                    }
302                } else {
303                    if (DBG) log("Missing id while parsing configuration");
304                }
305            }
306        } catch (EOFException ignore) {
307        } catch (IOException e) {
308            loge("Error parsing configuration: " + e);
309        } finally {
310            if (in != null) {
311                try {
312                    in.close();
313                } catch (Exception e) {}
314            }
315        }
316
317        return networks;
318    }
319
320    protected void loge(String s) {
321        Log.e(TAG, s);
322    }
323
324    protected void log(String s) {
325        Log.d(TAG, s);
326    }
327}
328