1/*
2 * Copyright (C) 2009 Qualcomm Innovation Center, Inc.  All Rights Reserved.
3 * Copyright (C) 2009 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.internal.telephony.dataconnection;
19
20import android.net.LinkAddress;
21import android.net.LinkProperties;
22import android.net.NetworkUtils;
23import android.net.RouteInfo;
24import android.os.SystemProperties;
25import android.telephony.Rlog;
26
27import com.android.internal.telephony.PhoneConstants;
28import com.android.internal.telephony.dataconnection.DcFailCause;
29
30import java.net.Inet4Address;
31import java.net.InetAddress;
32import java.net.UnknownHostException;
33
34/**
35 * This is RIL_Data_Call_Response_v5 from ril.h
36 */
37public class DataCallResponse {
38    private final boolean DBG = true;
39    private final String LOG_TAG = "DataCallResponse";
40
41    public int version = 0;
42    public int status = 0;
43    public int cid = 0;
44    public int active = 0;
45    public String type = "";
46    public String ifname = "";
47    public String [] addresses = new String[0];
48    public String [] dnses = new String[0];
49    public String[] gateways = new String[0];
50    public int suggestedRetryTime = -1;
51    public String [] pcscf = new String[0];
52    public int mtu = PhoneConstants.UNSET_MTU;
53
54    /**
55     * Class returned by onSetupConnectionCompleted.
56     */
57    public enum SetupResult {
58        SUCCESS,
59        ERR_BadCommand,
60        ERR_UnacceptableParameter,
61        ERR_GetLastErrorFromRil,
62        ERR_Stale,
63        ERR_RilError;
64
65        public DcFailCause mFailCause;
66
67        SetupResult() {
68            mFailCause = DcFailCause.fromInt(0);
69        }
70
71        @Override
72        public String toString() {
73            return name() + "  SetupResult.mFailCause=" + mFailCause;
74        }
75    }
76
77    @Override
78    public String toString() {
79        StringBuffer sb = new StringBuffer();
80        sb.append("DataCallResponse: {")
81           .append("version=").append(version)
82           .append(" status=").append(status)
83           .append(" retry=").append(suggestedRetryTime)
84           .append(" cid=").append(cid)
85           .append(" active=").append(active)
86           .append(" type=").append(type)
87           .append(" ifname=").append(ifname)
88           .append(" mtu=").append(mtu)
89           .append(" addresses=[");
90        for (String addr : addresses) {
91            sb.append(addr);
92            sb.append(",");
93        }
94        if (addresses.length > 0) sb.deleteCharAt(sb.length()-1);
95        sb.append("] dnses=[");
96        for (String addr : dnses) {
97            sb.append(addr);
98            sb.append(",");
99        }
100        if (dnses.length > 0) sb.deleteCharAt(sb.length()-1);
101        sb.append("] gateways=[");
102        for (String addr : gateways) {
103            sb.append(addr);
104            sb.append(",");
105        }
106        if (gateways.length > 0) sb.deleteCharAt(sb.length()-1);
107        sb.append("] pcscf=[");
108        for (String addr : pcscf) {
109            sb.append(addr);
110            sb.append(",");
111        }
112        if (pcscf.length > 0) sb.deleteCharAt(sb.length()-1);
113        sb.append("]}");
114        return sb.toString();
115    }
116
117    public SetupResult setLinkProperties(LinkProperties linkProperties,
118            boolean okToUseSystemPropertyDns) {
119        SetupResult result;
120
121        // Start with clean network properties and if we have
122        // a failure we'll clear again at the bottom of this code.
123        if (linkProperties == null)
124            linkProperties = new LinkProperties();
125        else
126            linkProperties.clear();
127
128        if (status == DcFailCause.NONE.getErrorCode()) {
129            String propertyPrefix = "net." + ifname + ".";
130
131            try {
132                // set interface name
133                linkProperties.setInterfaceName(ifname);
134
135                // set link addresses
136                if (addresses != null && addresses.length > 0) {
137                    for (String addr : addresses) {
138                        addr = addr.trim();
139                        if (addr.isEmpty()) continue;
140                        LinkAddress la;
141                        int addrPrefixLen;
142
143                        String [] ap = addr.split("/");
144                        if (ap.length == 2) {
145                            addr = ap[0];
146                            addrPrefixLen = Integer.parseInt(ap[1]);
147                        } else {
148                            addrPrefixLen = 0;
149                        }
150                        InetAddress ia;
151                        try {
152                            ia = NetworkUtils.numericToInetAddress(addr);
153                        } catch (IllegalArgumentException e) {
154                            throw new UnknownHostException("Non-numeric ip addr=" + addr);
155                        }
156                        if (! ia.isAnyLocalAddress()) {
157                            if (addrPrefixLen == 0) {
158                                // Assume point to point
159                                addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
160                            }
161                            if (DBG) Rlog.d(LOG_TAG, "addr/pl=" + addr + "/" + addrPrefixLen);
162                            try {
163                                la = new LinkAddress(ia, addrPrefixLen);
164                            } catch (IllegalArgumentException e) {
165                                throw new UnknownHostException("Bad parameter for LinkAddress, ia="
166                                        + ia.getHostAddress() + "/" + addrPrefixLen);
167                            }
168
169                            linkProperties.addLinkAddress(la);
170                        }
171                    }
172                } else {
173                    throw new UnknownHostException("no address for ifname=" + ifname);
174                }
175
176                // set dns servers
177                if (dnses != null && dnses.length > 0) {
178                    for (String addr : dnses) {
179                        addr = addr.trim();
180                        if (addr.isEmpty()) continue;
181                        InetAddress ia;
182                        try {
183                            ia = NetworkUtils.numericToInetAddress(addr);
184                        } catch (IllegalArgumentException e) {
185                            throw new UnknownHostException("Non-numeric dns addr=" + addr);
186                        }
187                        if (! ia.isAnyLocalAddress()) {
188                            linkProperties.addDnsServer(ia);
189                        }
190                    }
191                } else if (okToUseSystemPropertyDns){
192                    String dnsServers[] = new String[2];
193                    dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
194                    dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
195                    for (String dnsAddr : dnsServers) {
196                        dnsAddr = dnsAddr.trim();
197                        if (dnsAddr.isEmpty()) continue;
198                        InetAddress ia;
199                        try {
200                            ia = NetworkUtils.numericToInetAddress(dnsAddr);
201                        } catch (IllegalArgumentException e) {
202                            throw new UnknownHostException("Non-numeric dns addr=" + dnsAddr);
203                        }
204                        if (! ia.isAnyLocalAddress()) {
205                            linkProperties.addDnsServer(ia);
206                        }
207                    }
208                } else {
209                    throw new UnknownHostException("Empty dns response and no system default dns");
210                }
211
212                // set gateways
213                if ((gateways == null) || (gateways.length == 0)) {
214                    String sysGateways = SystemProperties.get(propertyPrefix + "gw");
215                    if (sysGateways != null) {
216                        gateways = sysGateways.split(" ");
217                    } else {
218                        gateways = new String[0];
219                    }
220                }
221                for (String addr : gateways) {
222                    addr = addr.trim();
223                    if (addr.isEmpty()) continue;
224                    InetAddress ia;
225                    try {
226                        ia = NetworkUtils.numericToInetAddress(addr);
227                    } catch (IllegalArgumentException e) {
228                        throw new UnknownHostException("Non-numeric gateway addr=" + addr);
229                    }
230                    // Allow 0.0.0.0 or :: as a gateway; this indicates a point-to-point interface.
231                    linkProperties.addRoute(new RouteInfo(ia));
232                }
233
234                // set interface MTU
235                // this may clobber the setting read from the APN db, but that's ok
236                linkProperties.setMtu(mtu);
237
238                result = SetupResult.SUCCESS;
239            } catch (UnknownHostException e) {
240                Rlog.d(LOG_TAG, "setLinkProperties: UnknownHostException " + e);
241                e.printStackTrace();
242                result = SetupResult.ERR_UnacceptableParameter;
243            }
244        } else {
245            if (version < 4) {
246                result = SetupResult.ERR_GetLastErrorFromRil;
247            } else {
248                result = SetupResult.ERR_RilError;
249            }
250        }
251
252        // An error occurred so clear properties
253        if (result != SetupResult.SUCCESS) {
254            if(DBG) {
255                Rlog.d(LOG_TAG, "setLinkProperties: error clearing LinkProperties " +
256                        "status=" + status + " result=" + result);
257            }
258            linkProperties.clear();
259        }
260
261        return result;
262    }
263}
264