blob: 0dbb9b0fa96d420c0d38d2ae8738268ea05fed33 [file] [log] [blame]
Sanket Khidkikar9f55c072014-06-18 11:58:46 -07001/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#define LOG_NDEBUG 0
31#define LOG_NDDEBUG 0
32#define LOG_NIDEBUG 0
33
34#include <stdlib.h>
35#include <errno.h>
36#include <fcntl.h>
37
38#include <sys/types.h>
39
40#include <cutils/log.h>
41#include "QcRouteController.h"
42
43const char *TAG = "QcRouteController";
44static char IP_PATH[] = "/system/bin/ip";
45const char *QcRouteController::MAIN_TABLE = "254";
46const char *QcRouteController::SOURCE_POLICY_RULE_PRIO = "150";
47const int MAXSIZE = 256;
48
49
50QcRouteController::QcRouteController() {
51}
52
53QcRouteController::~QcRouteController() {
54}
55
56std::string QcRouteController::_runIpCmd(const char * cmd) {
57 FILE *fp = NULL;
58 char line[MAXSIZE];
59 std::string res, buffer;
60
61 if (strlen(cmd) > 255) {
62 return std::string(strerror(E2BIG));
63 }
64
65 buffer = IP_PATH;
66 buffer += " ";
67 buffer += cmd;
68 buffer += " 2>&1"; //capture stderr
69
70 ALOGV(TAG,"%s", buffer.c_str());
71
72 if ((fp = popen(buffer.c_str(),"r")) == NULL) {
73 ALOGE(TAG, "failed to popen: %s", strerror(errno));
74 res = (strerror(errno));
75 } else if (fgets(line, sizeof line, fp)) {
76 ALOGV(TAG, "%s", line);
77 res = cmd;
78 res += ": ";
79 res += line;
80 }
81 pclose(fp);
82
83 return res;
84}
85
86std::string QcRouteController::repSrcRoute
87(
88 const char *iface,
89 const char *srcPrefix,
90 const char *gateway,
91 const char *table,
92 const char *ipver
93)
94{
95 std::string res = _repDefRoute(iface, gateway, table, ipver);
96 if (res.empty()) {
97 _delRule(table, ipver);
98 res = _addRule(srcPrefix, table, ipver);
99 if (res.empty())
100 res = _flushCache();
101 }
102
103 return res;
104}
105
106std::string QcRouteController::delSrcRoute
107(
108 const char *table,
109 const char *ipver
110)
111{
112 //if iface is down then route is probably purged; ignore the error.
113 _delDefRoute(table, ipver);
114 std::string res = _delRule(table, ipver);
115 if (res.empty())
116 res = _flushCache();
117
118 return res;
119}
120
121std::string QcRouteController::addDstRoute
122(
123 const char *iface,
124 const char *dstPrefix,
125 const char *gateway,
126 const int metric,
127 const char *table
128)
129{
130 char buffer[255];
131
132 if (gateway) {
133 snprintf(buffer, sizeof buffer,
134 "route add %s via %s dev %s table %s metric %d",
135 dstPrefix, gateway, iface, table, metric);
136 } else {
137 snprintf(buffer, sizeof buffer,
138 "route add %s dev %s table %s metric %d",
139 dstPrefix, iface, table, metric);
140 }
141
142 //blindly delete an indentical route if it exists.
143 _delHostRoute(dstPrefix, table);
144
145 std::string res = _runIpCmd(buffer);
146 if (res.empty() || (res.find("exists") != std::string::npos))
147 res = _flushCache();
148
149 return res;
150}
151
152std::string QcRouteController::delDstRoute
153(
154 const char *dstPrefix,
155 const char *table
156)
157{
158 std::string res = _delHostRoute(dstPrefix, table);
159 if (res.empty())
160 res = _flushCache();
161
162 return res;
163}
164
165std::string QcRouteController::_delHostRoute
166(
167 const char *dstPrefix,
168 const char *table
169)
170{
171 char buffer[255];
172 snprintf(buffer, sizeof buffer, "route del %s table %s",
173 dstPrefix, table);
174
175 return _runIpCmd(buffer);
176}
177
178std::string QcRouteController::replaceDefRoute
179(
180 const char *iface,
181 const char *gateway,
182 const char *ipver
183)
184{
185 std::string res = _repDefRoute(iface, gateway, MAIN_TABLE, ipver);
186 if (res.empty())
187 res = _flushCache();
188
189 return res;
190}
191
192std::string QcRouteController::_repDefRoute
193(
194 const char *iface,
195 const char *gateway,
196 const char *table,
197 const char *ipver
198)
199{
200 char buffer[255];
201
202 if (gateway) {
203 snprintf(buffer, sizeof buffer,
204 "%s route replace default via %s dev %s scope global table %s",
205 ipver, gateway, iface, table);
206 } else {
207 snprintf(buffer, sizeof buffer,
208 "%s route replace default dev %s table %s",
209 ipver, iface, table);
210 }
211
212 return _runIpCmd(buffer);
213}
214
215std::string QcRouteController::_delDefRoute
216(
217 const char *table,
218 const char *ipver,
219 const char *iface
220)
221{
222 char buffer[255];
223
224 if (iface) {
225 snprintf(buffer, sizeof buffer,
226 "%s route del default dev %s table %s",
227 ipver, iface, table);
228 } else {
229 snprintf(buffer, sizeof buffer,
230 "%s route del default table %s", ipver, table);
231 }
232
233 return _runIpCmd(buffer);
234}
235
236std::string QcRouteController::addDefRoute
237(
238 const char *iface,
239 const char *gateway,
240 const char *ipver,
241 const int metric,
242 const char *table
243)
244{
245 char buffer[255];
246
247 //remove existing def route for an iface before adding one with new metric
248 _delDefRoute(table, ipver, iface);
249
250 if (gateway) {
251 snprintf(buffer, sizeof buffer,
252 "%s route add default via %s dev %s table %s metric %d",
253 ipver, gateway, iface, table, metric);
254 } else {
255 snprintf(buffer, sizeof buffer,
256 "%s route add default dev %s table %s metric %d",
257 ipver, iface, table, metric);
258 }
259
260 std::string res = _runIpCmd(buffer);
261 if (res.empty())
262 res = _flushCache();
263
264 return res;
265}
266
267std::string QcRouteController::_flushCache() {
268 char buffer[255];
269
270 snprintf(buffer, sizeof buffer, "route flush cached");
271
272 return _runIpCmd(buffer);
273}
274
275std::string QcRouteController::_addRule
276(
277 const char *address,
278 const char *table,
279 const char *ipver
280)
281{
282 char buffer[255];
283
284 snprintf(buffer, sizeof buffer,
285 "%s rule add from %s lookup %s prio %s", ipver, address, table,
286 SOURCE_POLICY_RULE_PRIO);
287
288 return _runIpCmd(buffer);
289}
290
291std::string QcRouteController::_delRule
292(
293 const char *table,
294 const char *ipver
295)
296{
297 char buffer[255];
298
299 snprintf(buffer, sizeof buffer,
300 "%s rule del table %s", ipver, table);
301
302 return _runIpCmd(buffer);
303}