blob: 140cb36b1a1eaad127534881fda1d81decee6994 [file] [log] [blame]
San Mehat9ff78fb2010-01-19 12:59:15 -08001/*
2 * Copyright (C) 2008 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
JP Abgrall0031cea2012-04-17 16:38:23 -070017// #define LOG_NDEBUG 0
18
San Mehat9ff78fb2010-01-19 12:59:15 -080019#include <stdlib.h>
20#include <errno.h>
21#include <sys/socket.h>
22#include <sys/stat.h>
Rom Lemarchand001f0a42013-01-31 12:41:03 -080023#include <sys/wait.h>
San Mehat9ff78fb2010-01-19 12:59:15 -080024#include <fcntl.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
Olivier Baillyff2c0d82010-11-17 11:45:07 -080027#include <string.h>
John Michelauac208602011-05-27 22:07:20 -050028#include <cutils/properties.h>
San Mehat9ff78fb2010-01-19 12:59:15 -080029
30#define LOG_TAG "NatController"
31#include <cutils/log.h>
Rom Lemarchand001f0a42013-01-31 12:41:03 -080032#include <logwrap/logwrap.h>
San Mehat9ff78fb2010-01-19 12:59:15 -080033
34#include "NatController.h"
Robert Greenwaltfc97b822011-11-02 16:48:36 -070035#include "SecondaryTableController.h"
Robert Greenwaltc4621772012-01-31 12:46:45 -080036#include "NetdConstants.h"
San Mehat9ff78fb2010-01-19 12:59:15 -080037
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070038const char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
39const char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
40
Robert Greenwaltfc97b822011-11-02 16:48:36 -070041NatController::NatController(SecondaryTableController *ctrl) {
42 secondaryTableCtrl = ctrl;
San Mehat9ff78fb2010-01-19 12:59:15 -080043}
44
45NatController::~NatController() {
46}
47
JP Abgrall4ae80de2013-03-14 20:06:20 -070048struct CommandsAndArgs {
49 /* The array size doesn't really matter as the compiler will barf if too many initializers are specified. */
50 const char *cmd[32];
51 bool checkRes;
52};
53
Rom Lemarchand001f0a42013-01-31 12:41:03 -080054int NatController::runCmd(int argc, const char **argv) {
JP Abgrall11b4e9b2011-08-11 15:34:49 -070055 int res;
San Mehat9ff78fb2010-01-19 12:59:15 -080056
Rom Lemarchand001f0a42013-01-31 12:41:03 -080057 res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
58 ALOGV("runCmd() res=%d", res);
JP Abgrall11b4e9b2011-08-11 15:34:49 -070059 return res;
San Mehat9ff78fb2010-01-19 12:59:15 -080060}
61
JP Abgrall0031cea2012-04-17 16:38:23 -070062int NatController::setupIptablesHooks() {
JP Abgrall458f3182012-04-24 21:30:43 -070063 setDefaults();
JP Abgrall0031cea2012-04-17 16:38:23 -070064 return 0;
65}
66
67int NatController::setDefaults() {
JP Abgrall4ae80de2013-03-14 20:06:20 -070068 struct CommandsAndArgs defaultCommands[] = {
69 {{IPTABLES_PATH, "-F", "natctrl_FORWARD",}, 1},
JP Abgrall659692a2013-03-14 20:07:17 -070070 {{IPTABLES_PATH, "-A", "natctrl_FORWARD", "-j", "DROP"}, 1},
JP Abgrall4ae80de2013-03-14 20:06:20 -070071 {{IPTABLES_PATH, "-t", "nat", "-F", "natctrl_nat_POSTROUTING"}, 1},
72 {{IP_PATH, "rule", "flush"}, 0},
73 {{IP_PATH, "-6", "rule", "flush"}, 0},
74 {{IP_PATH, "rule", "add", "from", "all", "lookup", "default", "prio", "32767"}, 0},
75 {{IP_PATH, "rule", "add", "from", "all", "lookup", "main", "prio", "32766"}, 0},
76 {{IP_PATH, "-6", "rule", "add", "from", "all", "lookup", "default", "prio", "32767"}, 0},
77 {{IP_PATH, "-6", "rule", "add", "from", "all", "lookup", "main", "prio", "32766"}, 0},
78 {{IP_PATH, "route", "flush", "cache"}, 0},
Rom Lemarchand001f0a42013-01-31 12:41:03 -080079 };
JP Abgrall4ae80de2013-03-14 20:06:20 -070080 for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE(defaultCommands); cmdNum++) {
81 if (runCmd(ARRAY_SIZE(defaultCommands[cmdNum].cmd), defaultCommands[cmdNum].cmd) &&
82 defaultCommands[cmdNum].checkRes) {
83 return -1;
84 }
85 }
Robert Greenwaltfc97b822011-11-02 16:48:36 -070086
87 natCount = 0;
Kazuhiro Ondo4ab46852012-01-12 16:15:06 -060088
San Mehat9ff78fb2010-01-19 12:59:15 -080089 return 0;
90}
91
Robert Greenwaltfc97b822011-11-02 16:48:36 -070092bool NatController::checkInterface(const char *iface) {
Jaime A Lopez-Sollanod14fd4f2012-01-11 16:29:28 -080093 if (strlen(iface) > IFNAMSIZ) return false;
San Mehat9ff78fb2010-01-19 12:59:15 -080094 return true;
95}
96
JP Abgrall4ae80de2013-03-14 20:06:20 -070097int NatController::routesOp(bool add, const char *intIface, const char *extIface, char **argv, int addrCount) {
98 int tableNumber = secondaryTableCtrl->findTableNumber(extIface);
99 int ret = 0;
100
101 if (tableNumber != -1) {
102 for (int i = 0; i < addrCount; i++) {
103 if (add) {
104 ret |= secondaryTableCtrl->modifyFromRule(tableNumber, ADD, argv[5+i]);
105 ret |= secondaryTableCtrl->modifyLocalRoute(tableNumber, ADD, intIface, argv[5+i]);
106 } else {
107 ret |= secondaryTableCtrl->modifyLocalRoute(tableNumber, DEL, intIface, argv[5+i]);
108 ret |= secondaryTableCtrl->modifyFromRule(tableNumber, DEL, argv[5+i]);
109 }
110 }
111 const char *cmd[] = {
112 IP_PATH,
113 "route",
114 "flush",
115 "cache"
116 };
117 runCmd(ARRAY_SIZE(cmd), cmd);
118 }
119 return ret;
120}
121
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700122// 0 1 2 3 4 5
123// nat enable intface extface addrcnt nated-ipaddr/prelength
124int NatController::enableNat(const int argc, char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700125 int i;
126 int addrCount = atoi(argv[4]);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700127 const char *intIface = argv[2];
128 const char *extIface = argv[3];
129 int tableNumber;
San Mehat9ff78fb2010-01-19 12:59:15 -0800130
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700131 if (!checkInterface(intIface) || !checkInterface(extIface)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000132 ALOGE("Invalid interface specified");
San Mehat9ff78fb2010-01-19 12:59:15 -0800133 errno = ENODEV;
134 return -1;
135 }
136
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700137 if (argc < 5 + addrCount) {
Steve Block5ea0c052012-01-06 19:18:11 +0000138 ALOGE("Missing Argument");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700139 errno = EINVAL;
140 return -1;
141 }
JP Abgrall659692a2013-03-14 20:07:17 -0700142 if (routesOp(true, intIface, extIface, argv, addrCount)) {
143 ALOGE("Error setting route rules");
144 routesOp(false, intIface, extIface, argv, addrCount);
145 errno = ENODEV;
146 return -1;
147 }
148
149 // add this if we are the first added nat
150 if (natCount == 0) {
151 const char *cmd[] = {
152 IPTABLES_PATH,
153 "-t",
154 "nat",
155 "-A",
156 "natctrl_nat_POSTROUTING",
157 "-o",
158 extIface,
159 "-j",
160 "MASQUERADE"
161 };
162 if (runCmd(ARRAY_SIZE(cmd), cmd)) {
163 ALOGE("Error seting postroute rule: iface=%s", extIface);
164 // unwind what's been done, but don't care about success - what more could we do?
165 routesOp(false, intIface, extIface, argv, addrCount);
166 setDefaults();
167 return -1;
168 }
169 }
170
171
172 if (setForwardRules(true, intIface, extIface) != 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000173 ALOGE("Error setting forward rules");
JP Abgrall4ae80de2013-03-14 20:06:20 -0700174 routesOp(false, intIface, extIface, argv, addrCount);
JP Abgrall659692a2013-03-14 20:07:17 -0700175 if (natCount == 0) {
176 setDefaults();
177 }
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700178 errno = ENODEV;
179 return -1;
180 }
181
JP Abgrall0031cea2012-04-17 16:38:23 -0700182 /* Always make sure the drop rule is at the end */
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800183 const char *cmd1[] = {
184 IPTABLES_PATH,
185 "-D",
186 "natctrl_FORWARD",
187 "-j",
188 "DROP"
189 };
190 runCmd(ARRAY_SIZE(cmd1), cmd1);
191 const char *cmd2[] = {
192 IPTABLES_PATH,
193 "-A",
194 "natctrl_FORWARD",
195 "-j",
196 "DROP"
197 };
198 runCmd(ARRAY_SIZE(cmd2), cmd2);
JP Abgrall0031cea2012-04-17 16:38:23 -0700199
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700200 natCount++;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700201 return 0;
202}
203
204int NatController::setForwardRules(bool add, const char *intIface, const char * extIface) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800205 const char *cmd1[] = {
206 IPTABLES_PATH,
207 add ? "-A" : "-D",
208 "natctrl_FORWARD",
209 "-i",
210 extIface,
211 "-o",
212 intIface,
213 "-m",
214 "state",
215 "--state",
216 "ESTABLISHED,RELATED",
217 "-j",
218 "RETURN"
219 };
220 int rc = 0;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700221
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800222 if (runCmd(ARRAY_SIZE(cmd1), cmd1) && add) {
San Mehat9ff78fb2010-01-19 12:59:15 -0800223 return -1;
224 }
225
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800226 const char *cmd2[] = {
227 IPTABLES_PATH,
228 add ? "-A" : "-D",
229 "natctrl_FORWARD",
230 "-i",
231 intIface,
232 "-o",
233 extIface,
234 "-m",
235 "state",
236 "--state",
237 "INVALID",
238 "-j",
239 "DROP"
240 };
241
242 const char *cmd3[] = {
243 IPTABLES_PATH,
244 add ? "-A" : "-D",
245 "natctrl_FORWARD",
246 "-i",
247 intIface,
248 "-o",
249 extIface,
250 "-j",
251 "RETURN"
252 };
253
254 if (runCmd(ARRAY_SIZE(cmd2), cmd2) && add) {
Robert Greenwaltf7bf29c2011-11-01 22:07:28 -0700255 // bail on error, but only if adding
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800256 rc = -1;
257 goto err_invalid_drop;
Robert Greenwaltddb9f6e2011-08-02 13:00:11 -0700258 }
259
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800260 if (runCmd(ARRAY_SIZE(cmd3), cmd3) && add) {
Robert Greenwalt210b9772010-03-25 14:54:45 -0700261 // unwind what's been done, but don't care about success - what more could we do?
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800262 rc = -1;
263 goto err_return;
San Mehat9ff78fb2010-01-19 12:59:15 -0800264 }
JP Abgrall0031cea2012-04-17 16:38:23 -0700265
San Mehat9ff78fb2010-01-19 12:59:15 -0800266 return 0;
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800267
268err_return:
269 cmd2[1] = "-D";
270 runCmd(ARRAY_SIZE(cmd2), cmd2);
271err_invalid_drop:
272 cmd1[1] = "-D";
273 runCmd(ARRAY_SIZE(cmd1), cmd1);
274 return rc;
San Mehat9ff78fb2010-01-19 12:59:15 -0800275}
276
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700277// nat disable intface extface
278// 0 1 2 3 4 5
279// nat enable intface extface addrcnt nated-ipaddr/prelength
280int NatController::disableNat(const int argc, char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700281 int i;
282 int addrCount = atoi(argv[4]);
283 const char *intIface = argv[2];
284 const char *extIface = argv[3];
285 int tableNumber;
Robert Greenwalt1caafe62010-03-24 15:43:00 -0700286
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700287 if (!checkInterface(intIface) || !checkInterface(extIface)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000288 ALOGE("Invalid interface specified");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700289 errno = ENODEV;
290 return -1;
291 }
292
293 if (argc < 5 + addrCount) {
Steve Block5ea0c052012-01-06 19:18:11 +0000294 ALOGE("Missing Argument");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700295 errno = EINVAL;
296 return -1;
297 }
298
299 setForwardRules(false, intIface, extIface);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700300 routesOp(false, intIface, extIface, argv, addrCount);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700301 if (--natCount <= 0) {
Kazuhiro Ondo4ab46852012-01-12 16:15:06 -0600302 // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
303 setDefaults();
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700304 }
305 return 0;
San Mehat9ff78fb2010-01-19 12:59:15 -0800306}