1/*
2 * Copyright (C) 2010 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 android.net;
18
19import android.text.TextUtils;
20import android.util.Log;
21
22import java.net.Inet4Address;
23import java.net.InetAddress;
24import java.util.ArrayList;
25import java.util.Collection;
26import java.util.Collections;
27
28/**
29 * A simple object for retrieving the results of a DHCP request.
30 * Replaces (internally) the IPv4-only DhcpInfo class.
31 * @hide
32 */
33public class DhcpInfoInternal {
34    private final static String TAG = "DhcpInfoInternal";
35    public String ipAddress;
36    public int prefixLength;
37
38    public String dns1;
39    public String dns2;
40
41    public String serverAddress;
42    public int leaseDuration;
43
44    /**
45     * Vendor specific information (from RFC 2132).
46     */
47    public String vendorInfo;
48
49    private Collection<RouteInfo> mRoutes;
50
51    public DhcpInfoInternal() {
52        mRoutes = new ArrayList<RouteInfo>();
53    }
54
55    public void addRoute(RouteInfo routeInfo) {
56        mRoutes.add(routeInfo);
57    }
58
59    public Collection<RouteInfo> getRoutes() {
60        return Collections.unmodifiableCollection(mRoutes);
61    }
62
63    private int convertToInt(String addr) {
64        if (addr != null) {
65            try {
66                InetAddress inetAddress = NetworkUtils.numericToInetAddress(addr);
67                if (inetAddress instanceof Inet4Address) {
68                    return NetworkUtils.inetAddressToInt(inetAddress);
69                }
70            } catch (IllegalArgumentException e) {}
71        }
72        return 0;
73    }
74
75    public DhcpInfo makeDhcpInfo() {
76        DhcpInfo info = new DhcpInfo();
77        info.ipAddress = convertToInt(ipAddress);
78        for (RouteInfo route : mRoutes) {
79            if (route.isDefaultRoute()) {
80                info.gateway = convertToInt(route.getGateway().getHostAddress());
81                break;
82            }
83        }
84        try {
85            InetAddress inetAddress = NetworkUtils.numericToInetAddress(ipAddress);
86            info.netmask = NetworkUtils.prefixLengthToNetmaskInt(prefixLength);
87        } catch (IllegalArgumentException e) {}
88        info.dns1 = convertToInt(dns1);
89        info.dns2 = convertToInt(dns2);
90        info.serverAddress = convertToInt(serverAddress);
91        info.leaseDuration = leaseDuration;
92        return info;
93    }
94
95    public LinkAddress makeLinkAddress() {
96        if (TextUtils.isEmpty(ipAddress)) {
97            Log.e(TAG, "makeLinkAddress with empty ipAddress");
98            return null;
99        }
100        return new LinkAddress(NetworkUtils.numericToInetAddress(ipAddress), prefixLength);
101    }
102
103    public LinkProperties makeLinkProperties() {
104        LinkProperties p = new LinkProperties();
105        p.addLinkAddress(makeLinkAddress());
106        for (RouteInfo route : mRoutes) {
107            p.addRoute(route);
108        }
109        //if empty, connectivity configures default DNS
110        if (TextUtils.isEmpty(dns1) == false) {
111            p.addDns(NetworkUtils.numericToInetAddress(dns1));
112        } else {
113            Log.d(TAG, "makeLinkProperties with empty dns1!");
114        }
115        if (TextUtils.isEmpty(dns2) == false) {
116            p.addDns(NetworkUtils.numericToInetAddress(dns2));
117        } else {
118            Log.d(TAG, "makeLinkProperties with empty dns2!");
119        }
120        return p;
121    }
122
123    /* Updates the DHCP fields that need to be retained from
124     * original DHCP request if the DHCP renewal shows them as
125     * being empty
126     */
127    public void updateFromDhcpRequest(DhcpInfoInternal orig) {
128        if (orig == null) return;
129
130        if (TextUtils.isEmpty(dns1)) {
131            dns1 = orig.dns1;
132        }
133
134        if (TextUtils.isEmpty(dns2)) {
135            dns2 = orig.dns2;
136        }
137
138        if (mRoutes.size() == 0) {
139            for (RouteInfo route : orig.getRoutes()) {
140                addRoute(route);
141            }
142        }
143    }
144
145    /**
146     * Test if this DHCP lease includes vendor hint that network link is
147     * metered, and sensitive to heavy data transfers.
148     */
149    public boolean hasMeteredHint() {
150        if (vendorInfo != null) {
151            return vendorInfo.contains("ANDROID_METERED");
152        } else {
153            return false;
154        }
155    }
156
157    public String toString() {
158        String routeString = "";
159        for (RouteInfo route : mRoutes) routeString += route.toString() + " | ";
160        return "addr: " + ipAddress + "/" + prefixLength +
161                " mRoutes: " + routeString +
162                " dns: " + dns1 + "," + dns2 +
163                " dhcpServer: " + serverAddress +
164                " leaseDuration: " + leaseDuration;
165    }
166}
167