San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 1 | /* |
| 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 Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 17 | #define LOG_NDEBUG 0 |
JP Abgrall | 0031cea | 2012-04-17 16:38:23 -0700 | [diff] [blame] | 18 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 19 | #include <string> |
| 20 | #include <vector> |
| 21 | |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 22 | #include <errno.h> |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 23 | #include <fcntl.h> |
| 24 | #include <stdlib.h> |
| 25 | #include <string.h> |
| 26 | #include <arpa/inet.h> |
| 27 | #include <linux/in.h> |
| 28 | #include <netinet/in.h> |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 29 | #include <sys/socket.h> |
| 30 | #include <sys/stat.h> |
Rom Lemarchand | 001f0a4 | 2013-01-31 12:41:03 -0800 | [diff] [blame] | 31 | #include <sys/wait.h> |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 32 | |
| 33 | #define LOG_TAG "NatController" |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 34 | #include <android-base/strings.h> |
Lorenzo Colitti | 4fcb4a0 | 2017-02-03 14:08:37 +0900 | [diff] [blame] | 35 | #include <android-base/stringprintf.h> |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 36 | #include <cutils/log.h> |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 37 | #include <cutils/properties.h> |
Rom Lemarchand | 001f0a4 | 2013-01-31 12:41:03 -0800 | [diff] [blame] | 38 | #include <logwrap/logwrap.h> |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 39 | |
| 40 | #include "NatController.h" |
Robert Greenwalt | c462177 | 2012-01-31 12:46:45 -0800 | [diff] [blame] | 41 | #include "NetdConstants.h" |
Sreeram Ramachandran | 87475a1 | 2014-07-15 16:20:28 -0700 | [diff] [blame] | 42 | #include "RouteController.h" |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 43 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 44 | using android::base::Join; |
Lorenzo Colitti | 4fcb4a0 | 2017-02-03 14:08:37 +0900 | [diff] [blame] | 45 | using android::base::StringPrintf; |
| 46 | |
Jeff Sharkey | 8e188ed | 2012-07-12 18:32:03 -0700 | [diff] [blame] | 47 | const char* NatController::LOCAL_FORWARD = "natctrl_FORWARD"; |
Lorenzo Colitti | e8164dd | 2014-10-02 20:46:23 +0900 | [diff] [blame] | 48 | const char* NatController::LOCAL_MANGLE_FORWARD = "natctrl_mangle_FORWARD"; |
Jeff Sharkey | 8e188ed | 2012-07-12 18:32:03 -0700 | [diff] [blame] | 49 | const char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING"; |
Lorenzo Colitti | 8917e45 | 2016-08-01 16:47:50 +0900 | [diff] [blame] | 50 | const char* NatController::LOCAL_RAW_PREROUTING = "natctrl_raw_PREROUTING"; |
JP Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 51 | const char* NatController::LOCAL_TETHER_COUNTERS_CHAIN = "natctrl_tether_counters"; |
Jeff Sharkey | 8e188ed | 2012-07-12 18:32:03 -0700 | [diff] [blame] | 52 | |
Lorenzo Colitti | 8e1cee9 | 2016-07-09 14:24:08 +0900 | [diff] [blame] | 53 | auto NatController::execFunction = android_fork_execvp; |
Lorenzo Colitti | 4fcb4a0 | 2017-02-03 14:08:37 +0900 | [diff] [blame] | 54 | auto NatController::iptablesRestoreFunction = execIptablesRestore; |
Lorenzo Colitti | 8e1cee9 | 2016-07-09 14:24:08 +0900 | [diff] [blame] | 55 | |
Sreeram Ramachandran | 87475a1 | 2014-07-15 16:20:28 -0700 | [diff] [blame] | 56 | NatController::NatController() { |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | NatController::~NatController() { |
| 60 | } |
| 61 | |
JP Abgrall | 4ae80de | 2013-03-14 20:06:20 -0700 | [diff] [blame] | 62 | struct CommandsAndArgs { |
| 63 | /* The array size doesn't really matter as the compiler will barf if too many initializers are specified. */ |
| 64 | const char *cmd[32]; |
| 65 | bool checkRes; |
| 66 | }; |
| 67 | |
JP Abgrall | 0031cea | 2012-04-17 16:38:23 -0700 | [diff] [blame] | 68 | int NatController::setupIptablesHooks() { |
JP Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 69 | int res; |
| 70 | res = setDefaults(); |
| 71 | if (res < 0) { |
| 72 | return res; |
| 73 | } |
| 74 | |
Lorenzo Colitti | 4fcb4a0 | 2017-02-03 14:08:37 +0900 | [diff] [blame] | 75 | // Used to limit downstream mss to the upstream pmtu so we don't end up fragmenting every large |
| 76 | // packet tethered devices send. This is IPv4-only, because in IPv6 we send the MTU in the RA. |
| 77 | // This is no longer optional and tethering will fail to start if it fails. |
| 78 | std::string mssRewriteCommand = StringPrintf( |
| 79 | "*mangle\n" |
| 80 | "-A %s -p tcp --tcp-flags SYN SYN -j TCPMSS --clamp-mss-to-pmtu\n" |
| 81 | "COMMIT\n", LOCAL_MANGLE_FORWARD); |
Lorenzo Colitti | 05cfd25 | 2016-07-10 23:15:46 +0900 | [diff] [blame] | 82 | |
Lorenzo Colitti | 4fcb4a0 | 2017-02-03 14:08:37 +0900 | [diff] [blame] | 83 | // This is for tethering counters. This chain is reached via --goto, and then RETURNS. |
| 84 | std::string defaultCommands = StringPrintf( |
| 85 | "*filter\n" |
| 86 | ":%s -\n" |
| 87 | "COMMIT\n", LOCAL_TETHER_COUNTERS_CHAIN); |
| 88 | |
| 89 | res = iptablesRestoreFunction(V4, mssRewriteCommand); |
| 90 | if (res < 0) { |
| 91 | return res; |
JP Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 92 | } |
Lorenzo Colitti | 4fcb4a0 | 2017-02-03 14:08:37 +0900 | [diff] [blame] | 93 | |
| 94 | res = iptablesRestoreFunction(V4V6, defaultCommands); |
| 95 | if (res < 0) { |
| 96 | return res; |
| 97 | } |
| 98 | |
JP Abgrall | f3cc83f | 2013-09-11 20:01:59 -0700 | [diff] [blame] | 99 | ifacePairList.clear(); |
JP Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 100 | |
JP Abgrall | 0031cea | 2012-04-17 16:38:23 -0700 | [diff] [blame] | 101 | return 0; |
| 102 | } |
| 103 | |
| 104 | int NatController::setDefaults() { |
Lorenzo Colitti | 4fcb4a0 | 2017-02-03 14:08:37 +0900 | [diff] [blame] | 105 | std::string v4Cmd = StringPrintf( |
| 106 | "*filter\n" |
| 107 | ":%s -\n" |
| 108 | "-A %s -j DROP\n" |
| 109 | "COMMIT\n" |
| 110 | "*nat\n" |
| 111 | ":%s -\n" |
| 112 | "COMMIT\n", LOCAL_FORWARD, LOCAL_FORWARD, LOCAL_NAT_POSTROUTING); |
| 113 | |
| 114 | std::string v6Cmd = StringPrintf( |
| 115 | "*filter\n" |
| 116 | ":%s -\n" |
| 117 | "COMMIT\n" |
| 118 | "*raw\n" |
| 119 | ":%s -\n" |
| 120 | "COMMIT\n", LOCAL_FORWARD, LOCAL_RAW_PREROUTING); |
| 121 | |
| 122 | int res = iptablesRestoreFunction(V4, v4Cmd); |
| 123 | if (res < 0) { |
| 124 | return res; |
| 125 | } |
| 126 | |
| 127 | res = iptablesRestoreFunction(V6, v6Cmd); |
| 128 | if (res < 0) { |
| 129 | return res; |
JP Abgrall | 4ae80de | 2013-03-14 20:06:20 -0700 | [diff] [blame] | 130 | } |
Robert Greenwalt | fc97b82 | 2011-11-02 16:48:36 -0700 | [diff] [blame] | 131 | |
| 132 | natCount = 0; |
Kazuhiro Ondo | 4ab4685 | 2012-01-12 16:15:06 -0600 | [diff] [blame] | 133 | |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 134 | return 0; |
| 135 | } |
| 136 | |
Sreeram Ramachandran | 87475a1 | 2014-07-15 16:20:28 -0700 | [diff] [blame] | 137 | int NatController::enableNat(const char* intIface, const char* extIface) { |
JP Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 138 | ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface); |
| 139 | |
JP Abgrall | 69261cb | 2014-06-19 18:35:24 -0700 | [diff] [blame] | 140 | if (!isIfaceName(intIface) || !isIfaceName(extIface)) { |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 141 | errno = ENODEV; |
| 142 | return -1; |
| 143 | } |
| 144 | |
JP Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 145 | /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */ |
| 146 | if (!strcmp(intIface, extIface)) { |
| 147 | ALOGE("Duplicate interface specified: %s %s", intIface, extIface); |
| 148 | errno = EINVAL; |
| 149 | return -1; |
| 150 | } |
| 151 | |
JP Abgrall | 659692a | 2013-03-14 20:07:17 -0700 | [diff] [blame] | 152 | // add this if we are the first added nat |
| 153 | if (natCount == 0) { |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 154 | std::vector<std::string> v4Cmds = { |
| 155 | "*nat", |
| 156 | StringPrintf("-A %s -o %s -j MASQUERADE", LOCAL_NAT_POSTROUTING, extIface), |
| 157 | "COMMIT\n" |
JP Abgrall | 659692a | 2013-03-14 20:07:17 -0700 | [diff] [blame] | 158 | }; |
Lorenzo Colitti | 05cfd25 | 2016-07-10 23:15:46 +0900 | [diff] [blame] | 159 | |
| 160 | /* |
| 161 | * IPv6 tethering doesn't need the state-based conntrack rules, so |
| 162 | * it unconditionally jumps to the tether counters chain all the time. |
| 163 | */ |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 164 | std::vector<std::string> v6Cmds = { |
| 165 | "*filter", |
| 166 | StringPrintf("-A %s -g %s", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN), |
| 167 | "COMMIT\n" |
| 168 | }; |
Lorenzo Colitti | 05cfd25 | 2016-07-10 23:15:46 +0900 | [diff] [blame] | 169 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 170 | if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n')) || |
| 171 | iptablesRestoreFunction(V6, Join(v6Cmds, '\n'))) { |
Sreeram Ramachandran | 87475a1 | 2014-07-15 16:20:28 -0700 | [diff] [blame] | 172 | ALOGE("Error setting postroute rule: iface=%s", extIface); |
JP Abgrall | 659692a | 2013-03-14 20:07:17 -0700 | [diff] [blame] | 173 | // unwind what's been done, but don't care about success - what more could we do? |
JP Abgrall | 659692a | 2013-03-14 20:07:17 -0700 | [diff] [blame] | 174 | setDefaults(); |
| 175 | return -1; |
| 176 | } |
| 177 | } |
| 178 | |
JP Abgrall | 659692a | 2013-03-14 20:07:17 -0700 | [diff] [blame] | 179 | if (setForwardRules(true, intIface, extIface) != 0) { |
Steve Block | 5ea0c05 | 2012-01-06 19:18:11 +0000 | [diff] [blame] | 180 | ALOGE("Error setting forward rules"); |
JP Abgrall | 659692a | 2013-03-14 20:07:17 -0700 | [diff] [blame] | 181 | if (natCount == 0) { |
| 182 | setDefaults(); |
| 183 | } |
Robert Greenwalt | fc97b82 | 2011-11-02 16:48:36 -0700 | [diff] [blame] | 184 | errno = ENODEV; |
| 185 | return -1; |
| 186 | } |
| 187 | |
| 188 | natCount++; |
Robert Greenwalt | fc97b82 | 2011-11-02 16:48:36 -0700 | [diff] [blame] | 189 | return 0; |
| 190 | } |
| 191 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 192 | bool NatController::checkTetherCountingRuleExist(const std::string& pair_name) { |
| 193 | return std::find(ifacePairList.begin(), ifacePairList.end(), pair_name) != ifacePairList.end(); |
JP Abgrall | f3cc83f | 2013-09-11 20:01:59 -0700 | [diff] [blame] | 194 | } |
| 195 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 196 | /* static */ |
| 197 | std::string NatController::makeTetherCountingRule(const char *if1, const char *if2) { |
| 198 | return StringPrintf("-A %s -i %s -o %s -j RETURN", LOCAL_TETHER_COUNTERS_CHAIN, if1, if2); |
JP Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 199 | } |
| 200 | |
| 201 | int NatController::setForwardRules(bool add, const char *intIface, const char *extIface) { |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 202 | const char *op = add ? "-A" : "-D"; |
Robert Greenwalt | fc97b82 | 2011-11-02 16:48:36 -0700 | [diff] [blame] | 203 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 204 | std::string rpfilterCmd = StringPrintf( |
| 205 | "*raw\n" |
| 206 | "%s %s -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n" |
| 207 | "COMMIT\n", op, LOCAL_RAW_PREROUTING, intIface); |
| 208 | if (iptablesRestoreFunction(V6, rpfilterCmd) == -1 && add) { |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 209 | return -1; |
| 210 | } |
| 211 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 212 | std::vector<std::string> v4 = { |
| 213 | "*filter", |
| 214 | StringPrintf("%s %s -i %s -o %s -m state --state ESTABLISHED,RELATED -g %s", |
| 215 | op, LOCAL_FORWARD, extIface, intIface, LOCAL_TETHER_COUNTERS_CHAIN), |
| 216 | StringPrintf("%s %s -i %s -o %s -m state --state INVALID -j DROP", |
| 217 | op, LOCAL_FORWARD, intIface, extIface), |
| 218 | StringPrintf("%s %s -i %s -o %s -g %s", |
| 219 | op, LOCAL_FORWARD, intIface, extIface, LOCAL_TETHER_COUNTERS_CHAIN), |
Rom Lemarchand | 001f0a4 | 2013-01-31 12:41:03 -0800 | [diff] [blame] | 220 | }; |
| 221 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 222 | std::vector<std::string> v6 = { |
| 223 | "*filter", |
Rom Lemarchand | 001f0a4 | 2013-01-31 12:41:03 -0800 | [diff] [blame] | 224 | }; |
| 225 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 226 | /* We only ever add tethering quota rules so that they stick. */ |
| 227 | std::string pair1 = StringPrintf("%s_%s", intIface, extIface); |
| 228 | if (add && !checkTetherCountingRuleExist(pair1)) { |
| 229 | v4.push_back(makeTetherCountingRule(intIface, extIface)); |
| 230 | v6.push_back(makeTetherCountingRule(intIface, extIface)); |
| 231 | } |
| 232 | std::string pair2 = StringPrintf("%s_%s", extIface, intIface); |
| 233 | if (add && !checkTetherCountingRuleExist(pair2)) { |
| 234 | v4.push_back(makeTetherCountingRule(extIface, intIface)); |
| 235 | v6.push_back(makeTetherCountingRule(extIface, intIface)); |
Robert Greenwalt | ddb9f6e | 2011-08-02 13:00:11 -0700 | [diff] [blame] | 236 | } |
| 237 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 238 | // Always make sure the drop rule is at the end. |
| 239 | // TODO: instead of doing this, consider just rebuilding LOCAL_FORWARD completely from scratch |
| 240 | // every time, starting with ":natctrl_FORWARD -\n". This method would likely be a bit simpler. |
| 241 | if (add) { |
| 242 | v4.push_back(StringPrintf("-D %s -j DROP", LOCAL_FORWARD)); |
| 243 | v4.push_back(StringPrintf("-A %s -j DROP", LOCAL_FORWARD)); |
| 244 | } |
| 245 | |
| 246 | v4.push_back("COMMIT\n"); |
| 247 | v6.push_back("COMMIT\n"); |
| 248 | |
| 249 | // We only add IPv6 rules here, never remove them. |
| 250 | if (iptablesRestoreFunction(V4, Join(v4, '\n')) == -1 || |
| 251 | (add && iptablesRestoreFunction(V6, Join(v6, '\n')) == -1)) { |
Robert Greenwalt | 210b977 | 2010-03-25 14:54:45 -0700 | [diff] [blame] | 252 | // unwind what's been done, but don't care about success - what more could we do? |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 253 | if (add) { |
| 254 | setForwardRules(false, intIface, extIface); |
| 255 | } |
| 256 | return -1; |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 257 | } |
JP Abgrall | 0031cea | 2012-04-17 16:38:23 -0700 | [diff] [blame] | 258 | |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 259 | if (add && !checkTetherCountingRuleExist(pair1)) { |
| 260 | ifacePairList.push_front(pair1); |
Lorenzo Colitti | 8917e45 | 2016-08-01 16:47:50 +0900 | [diff] [blame] | 261 | } |
Lorenzo Colitti | eb7eb3e | 2017-08-11 01:20:04 +0900 | [diff] [blame^] | 262 | if (add && !checkTetherCountingRuleExist(pair2)) { |
| 263 | ifacePairList.push_front(pair2); |
JP Abgrall | baeccc4 | 2013-06-25 09:44:10 -0700 | [diff] [blame] | 264 | } |
| 265 | |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 266 | return 0; |
| 267 | } |
| 268 | |
Sreeram Ramachandran | 87475a1 | 2014-07-15 16:20:28 -0700 | [diff] [blame] | 269 | int NatController::disableNat(const char* intIface, const char* extIface) { |
JP Abgrall | 69261cb | 2014-06-19 18:35:24 -0700 | [diff] [blame] | 270 | if (!isIfaceName(intIface) || !isIfaceName(extIface)) { |
Robert Greenwalt | fc97b82 | 2011-11-02 16:48:36 -0700 | [diff] [blame] | 271 | errno = ENODEV; |
| 272 | return -1; |
| 273 | } |
| 274 | |
Robert Greenwalt | fc97b82 | 2011-11-02 16:48:36 -0700 | [diff] [blame] | 275 | setForwardRules(false, intIface, extIface); |
Robert Greenwalt | fc97b82 | 2011-11-02 16:48:36 -0700 | [diff] [blame] | 276 | if (--natCount <= 0) { |
Kazuhiro Ondo | 4ab4685 | 2012-01-12 16:15:06 -0600 | [diff] [blame] | 277 | // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0 |
| 278 | setDefaults(); |
Robert Greenwalt | fc97b82 | 2011-11-02 16:48:36 -0700 | [diff] [blame] | 279 | } |
| 280 | return 0; |
San Mehat | 9ff78fb | 2010-01-19 12:59:15 -0800 | [diff] [blame] | 281 | } |