1d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey/* 2d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * Copyright (C) 2012 The Android Open Source Project 3d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * 4d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * you may not use this file except in compliance with the License. 6d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * You may obtain a copy of the License at 7d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * 8d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * 10d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * See the License for the specific language governing permissions and 14d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey * limitations under the License. 15d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey */ 16d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 17d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include <errno.h> 18d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include <stdio.h> 19d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include <stdlib.h> 20d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include <string.h> 21d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 22d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#define LOG_TAG "FirewallController" 23d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#define LOG_NDEBUG 0 24d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 25d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include <cutils/log.h> 26feb2b61d3010d52e530357116c3b22c6d77da3cfXiaohui Chen#include <private/android_filesystem_config.h> 27d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 28d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include "NetdConstants.h" 29d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include "FirewallController.h" 30d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 311cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chenconst char* FirewallController::TABLE = "filter"; 321cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 33d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyconst char* FirewallController::LOCAL_INPUT = "fw_INPUT"; 34d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyconst char* FirewallController::LOCAL_OUTPUT = "fw_OUTPUT"; 35d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyconst char* FirewallController::LOCAL_FORWARD = "fw_FORWARD"; 36d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 371cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chenconst char* FirewallController::LOCAL_DOZABLE = "fw_dozable"; 381cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chenconst char* FirewallController::LOCAL_STANDBY = "fw_standby"; 391cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 4012a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti// ICMPv6 types that are required for any form of IPv6 connectivity to work. Note that because the 4112a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti// fw_dozable chain is called from both INPUT and OUTPUT, this includes both packets that we need 4212a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti// to be able to send (e.g., RS, NS), and packets that we need to receive (e.g., RA, NA). 4312a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitticonst char* FirewallController::ICMPV6_TYPES[] = { 4412a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti "packet-too-big", 4512a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti "router-solicitation", 4612a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti "router-advertisement", 4712a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti "neighbour-solicitation", 4812a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti "neighbour-advertisement", 4912a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti "redirect", 5012a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti}; 5112a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti 52d8c64026aaae5a9987151b719bd840ec7d68747aJeff SharkeyFirewallController::FirewallController(void) { 53390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani // If no rules are set, it's in BLACKLIST mode 541cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen mFirewallType = BLACKLIST; 55d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 56d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 57d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint FirewallController::setupIptablesHooks(void) { 581cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen int res = 0; 591cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen // child chains are created but not attached, they will be attached explicitly. 601cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen FirewallType firewallType = getFirewallType(DOZABLE); 611cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= createChain(LOCAL_DOZABLE, LOCAL_INPUT, firewallType); 621cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 631cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen firewallType = getFirewallType(STANDBY); 641cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= createChain(LOCAL_STANDBY, LOCAL_INPUT, firewallType); 651cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 661cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return res; 67d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 68d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 69390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasaniint FirewallController::enableFirewall(FirewallType ftype) { 70d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey int res = 0; 711cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen if (mFirewallType != ftype) { 721cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen // flush any existing rules 731cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen disableFirewall(); 741cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 751cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen if (ftype == WHITELIST) { 761cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen // create default rule to drop all traffic 771cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, "-A", LOCAL_INPUT, "-j", "DROP", NULL); 781cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, "-A", LOCAL_OUTPUT, "-j", "REJECT", NULL); 791cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, "-A", LOCAL_FORWARD, "-j", "REJECT", NULL); 801cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen } 811cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 821cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen // Set this after calling disableFirewall(), since it defaults to WHITELIST there 831cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen mFirewallType = ftype; 84390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani } 85d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey return res; 86d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 87d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 88d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint FirewallController::disableFirewall(void) { 89d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey int res = 0; 90d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 911cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen mFirewallType = WHITELIST; 92390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani 93d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey // flush any existing rules 94d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(V4V6, "-F", LOCAL_INPUT, NULL); 95d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(V4V6, "-F", LOCAL_OUTPUT, NULL); 96d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(V4V6, "-F", LOCAL_FORWARD, NULL); 97d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 98d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey return res; 99d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 100d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 1011cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chenint FirewallController::enableChildChains(ChildChain chain, bool enable) { 1021cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen int res = 0; 1031cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen const char* name; 1041cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen switch(chain) { 1051cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen case DOZABLE: 1061cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen name = LOCAL_DOZABLE; 1071cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen break; 1081cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen case STANDBY: 1091cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen name = LOCAL_STANDBY; 1101cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen break; 1111cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen default: 1121cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return res; 1131cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen } 1141cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 1151cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen if (enable) { 1161cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= attachChain(name, LOCAL_INPUT); 1171cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= attachChain(name, LOCAL_OUTPUT); 1181cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen } else { 1191cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= detachChain(name, LOCAL_INPUT); 1201cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= detachChain(name, LOCAL_OUTPUT); 1211cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen } 1221cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return res; 1231cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen} 1241cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 125d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint FirewallController::isFirewallEnabled(void) { 126d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey // TODO: verify that rules are still in place near top 127d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey return -1; 128d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 129d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 130d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint FirewallController::setInterfaceRule(const char* iface, FirewallRule rule) { 1311cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen if (mFirewallType == BLACKLIST) { 132390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani // Unsupported in BLACKLIST mode 133390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani return -1; 134390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani } 135390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani 13669261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall if (!isIfaceName(iface)) { 13769261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall errno = ENOENT; 13869261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall return -1; 13969261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall } 14069261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall 141d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey const char* op; 142d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey if (rule == ALLOW) { 143d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey op = "-I"; 144d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } else { 145d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey op = "-D"; 146d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } 147d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 148d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey int res = 0; 149d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(V4V6, op, LOCAL_INPUT, "-i", iface, "-j", "RETURN", NULL); 150d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(V4V6, op, LOCAL_OUTPUT, "-o", iface, "-j", "RETURN", NULL); 151d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey return res; 152d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 153d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 154d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint FirewallController::setEgressSourceRule(const char* addr, FirewallRule rule) { 1551cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen if (mFirewallType == BLACKLIST) { 156390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani // Unsupported in BLACKLIST mode 157390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani return -1; 158390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani } 159390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani 160d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey IptablesTarget target = V4; 161d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey if (strchr(addr, ':')) { 162d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey target = V6; 163d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } 164d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 165d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey const char* op; 166d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey if (rule == ALLOW) { 167d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey op = "-I"; 168d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } else { 169d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey op = "-D"; 170d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } 171d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 172d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey int res = 0; 173d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(target, op, LOCAL_INPUT, "-d", addr, "-j", "RETURN", NULL); 174d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(target, op, LOCAL_OUTPUT, "-s", addr, "-j", "RETURN", NULL); 175d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey return res; 176d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 177d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 178d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint FirewallController::setEgressDestRule(const char* addr, int protocol, int port, 179d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey FirewallRule rule) { 1801cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen if (mFirewallType == BLACKLIST) { 181390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani // Unsupported in BLACKLIST mode 182390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani return -1; 183390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani } 184390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani 185d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey IptablesTarget target = V4; 186d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey if (strchr(addr, ':')) { 187d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey target = V6; 188d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } 189d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 190d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey char protocolStr[16]; 191d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey sprintf(protocolStr, "%d", protocol); 192d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 193d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey char portStr[16]; 194d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey sprintf(portStr, "%d", port); 195d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 196d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey const char* op; 197d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey if (rule == ALLOW) { 198d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey op = "-I"; 199d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } else { 200d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey op = "-D"; 201d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } 202d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 203d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey int res = 0; 204d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(target, op, LOCAL_INPUT, "-s", addr, "-p", protocolStr, 205d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey "--sport", portStr, "-j", "RETURN", NULL); 206d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey res |= execIptables(target, op, LOCAL_OUTPUT, "-d", addr, "-p", protocolStr, 207d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey "--dport", portStr, "-j", "RETURN", NULL); 208d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey return res; 209d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 210d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 2111cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui ChenFirewallType FirewallController::getFirewallType(ChildChain chain) { 2121cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen switch(chain) { 2131cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen case DOZABLE: 2141cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return WHITELIST; 2151cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen case STANDBY: 2161cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return BLACKLIST; 2171cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen case NONE: 2181cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return mFirewallType; 2191cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen default: 2201cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return BLACKLIST; 2211cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen } 2221cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen} 2231cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 2241cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chenint FirewallController::setUidRule(ChildChain chain, int uid, FirewallRule rule) { 225d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey char uidStr[16]; 226d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey sprintf(uidStr, "%d", uid); 227d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 228d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey const char* op; 229390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani const char* target; 2301cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen FirewallType firewallType = getFirewallType(chain); 231390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani if (firewallType == WHITELIST) { 232390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani target = "RETURN"; 233390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani op = (rule == ALLOW)? "-I" : "-D"; 234390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani } else { // BLACKLIST mode 235390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani target = "DROP"; 236390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani op = (rule == DENY)? "-I" : "-D"; 237d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey } 238d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey 239d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey int res = 0; 2401cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen switch(chain) { 2411cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen case DOZABLE: 2421cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, op, LOCAL_DOZABLE, "-m", "owner", "--uid-owner", 2431cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen uidStr, "-j", target, NULL); 2441cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen break; 2451cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen case STANDBY: 2461cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, op, LOCAL_STANDBY, "-m", "owner", "--uid-owner", 2471cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen uidStr, "-j", target, NULL); 2481cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen break; 2491cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen case NONE: 2501cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, op, LOCAL_INPUT, "-m", "owner", "--uid-owner", uidStr, 2511cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen "-j", target, NULL); 2521cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, op, LOCAL_OUTPUT, "-m", "owner", "--uid-owner", uidStr, 2531cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen "-j", target, NULL); 2541cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen break; 2551cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen default: 2561cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen ALOGW("Unknown child chain: %d", chain); 2571cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen break; 2581cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen } 2591cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return res; 2601cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen} 2611cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 2621cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chenint FirewallController::attachChain(const char* childChain, const char* parentChain) { 2631cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return execIptables(V4V6, "-t", TABLE, "-A", parentChain, "-j", childChain, NULL); 2641cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen} 2651cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 2661cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chenint FirewallController::detachChain(const char* childChain, const char* parentChain) { 2671cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen return execIptables(V4V6, "-t", TABLE, "-D", parentChain, "-j", childChain, NULL); 2681cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen} 2691cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen 2701cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chenint FirewallController::createChain(const char* childChain, 2711cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen const char* parentChain, FirewallType type) { 2721cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen // Order is important, otherwise later steps may fail. 2731cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen execIptablesSilently(V4V6, "-t", TABLE, "-D", parentChain, "-j", childChain, NULL); 2741cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen execIptablesSilently(V4V6, "-t", TABLE, "-F", childChain, NULL); 2751cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen execIptablesSilently(V4V6, "-t", TABLE, "-X", childChain, NULL); 2761cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen int res = 0; 2771cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, "-t", TABLE, "-N", childChain, NULL); 2781cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen if (type == WHITELIST) { 27912a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti // Allow ICMPv6 packets necessary to make IPv6 connectivity work. http://b/23158230 . 28012a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti for (size_t i = 0; i < ARRAY_SIZE(ICMPV6_TYPES); i++) { 28112a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti res |= execIptables(V6, "-A", childChain, "-p", "icmpv6", "--icmpv6-type", 28212a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti ICMPV6_TYPES[i], "-j", "RETURN", NULL); 28312a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti } 28412a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti 285feb2b61d3010d52e530357116c3b22c6d77da3cfXiaohui Chen // create default white list for system uid range 286feb2b61d3010d52e530357116c3b22c6d77da3cfXiaohui Chen char uidStr[16]; 287feb2b61d3010d52e530357116c3b22c6d77da3cfXiaohui Chen sprintf(uidStr, "0-%d", AID_APP - 1); 288feb2b61d3010d52e530357116c3b22c6d77da3cfXiaohui Chen res |= execIptables(V4V6, "-A", childChain, "-m", "owner", "--uid-owner", 289feb2b61d3010d52e530357116c3b22c6d77da3cfXiaohui Chen uidStr, "-j", "RETURN", NULL); 29012a76036b51139338e4329b0d7ec79bbc84e9580Lorenzo Colitti 2911cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen // create default rule to drop all traffic 2921cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen res |= execIptables(V4V6, "-A", childChain, "-j", "DROP", NULL); 2931cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen } 294d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey return res; 295d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey} 296