blob: 3f71d025b8688d9b6ee454c613d14d7cedbfa058 [file] [log] [blame]
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001/*
2 * Copyright (C) 2012 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
17#include <errno.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#define LOG_TAG "FirewallController"
23#define LOG_NDEBUG 0
24
25#include <cutils/log.h>
26
27#include "NetdConstants.h"
28#include "FirewallController.h"
29
30const char* FirewallController::LOCAL_INPUT = "fw_INPUT";
31const char* FirewallController::LOCAL_OUTPUT = "fw_OUTPUT";
32const char* FirewallController::LOCAL_FORWARD = "fw_FORWARD";
33
34FirewallController::FirewallController(void) {
Amith Yamasani390e4ea2015-04-25 19:08:57 -070035 // If no rules are set, it's in BLACKLIST mode
36 firewallType = BLACKLIST;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070037}
38
39int FirewallController::setupIptablesHooks(void) {
40 return 0;
41}
42
Amith Yamasani390e4ea2015-04-25 19:08:57 -070043int FirewallController::enableFirewall(FirewallType ftype) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070044 int res = 0;
45
46 // flush any existing rules
47 disableFirewall();
48
Amith Yamasani390e4ea2015-04-25 19:08:57 -070049 if (ftype == WHITELIST) {
50 // create default rule to drop all traffic
51 res |= execIptables(V4V6, "-A", LOCAL_INPUT, "-j", "DROP", NULL);
52 res |= execIptables(V4V6, "-A", LOCAL_OUTPUT, "-j", "REJECT", NULL);
53 res |= execIptables(V4V6, "-A", LOCAL_FORWARD, "-j", "REJECT", NULL);
54 }
55
56 // Set this after calling disableFirewall(), since it defaults to WHITELIST there
57 firewallType = ftype;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070058
59 return res;
60}
61
62int FirewallController::disableFirewall(void) {
63 int res = 0;
64
Amith Yamasani390e4ea2015-04-25 19:08:57 -070065 firewallType = WHITELIST;
66
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070067 // flush any existing rules
68 res |= execIptables(V4V6, "-F", LOCAL_INPUT, NULL);
69 res |= execIptables(V4V6, "-F", LOCAL_OUTPUT, NULL);
70 res |= execIptables(V4V6, "-F", LOCAL_FORWARD, NULL);
71
72 return res;
73}
74
75int FirewallController::isFirewallEnabled(void) {
76 // TODO: verify that rules are still in place near top
77 return -1;
78}
79
80int FirewallController::setInterfaceRule(const char* iface, FirewallRule rule) {
Amith Yamasani390e4ea2015-04-25 19:08:57 -070081 if (firewallType == BLACKLIST) {
82 // Unsupported in BLACKLIST mode
83 return -1;
84 }
85
JP Abgrall69261cb2014-06-19 18:35:24 -070086 if (!isIfaceName(iface)) {
87 errno = ENOENT;
88 return -1;
89 }
90
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070091 const char* op;
92 if (rule == ALLOW) {
93 op = "-I";
94 } else {
95 op = "-D";
96 }
97
98 int res = 0;
99 res |= execIptables(V4V6, op, LOCAL_INPUT, "-i", iface, "-j", "RETURN", NULL);
100 res |= execIptables(V4V6, op, LOCAL_OUTPUT, "-o", iface, "-j", "RETURN", NULL);
101 return res;
102}
103
104int FirewallController::setEgressSourceRule(const char* addr, FirewallRule rule) {
Amith Yamasani390e4ea2015-04-25 19:08:57 -0700105 if (firewallType == BLACKLIST) {
106 // Unsupported in BLACKLIST mode
107 return -1;
108 }
109
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700110 IptablesTarget target = V4;
111 if (strchr(addr, ':')) {
112 target = V6;
113 }
114
115 const char* op;
116 if (rule == ALLOW) {
117 op = "-I";
118 } else {
119 op = "-D";
120 }
121
122 int res = 0;
123 res |= execIptables(target, op, LOCAL_INPUT, "-d", addr, "-j", "RETURN", NULL);
124 res |= execIptables(target, op, LOCAL_OUTPUT, "-s", addr, "-j", "RETURN", NULL);
125 return res;
126}
127
128int FirewallController::setEgressDestRule(const char* addr, int protocol, int port,
129 FirewallRule rule) {
Amith Yamasani390e4ea2015-04-25 19:08:57 -0700130 if (firewallType == BLACKLIST) {
131 // Unsupported in BLACKLIST mode
132 return -1;
133 }
134
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700135 IptablesTarget target = V4;
136 if (strchr(addr, ':')) {
137 target = V6;
138 }
139
140 char protocolStr[16];
141 sprintf(protocolStr, "%d", protocol);
142
143 char portStr[16];
144 sprintf(portStr, "%d", port);
145
146 const char* op;
147 if (rule == ALLOW) {
148 op = "-I";
149 } else {
150 op = "-D";
151 }
152
153 int res = 0;
154 res |= execIptables(target, op, LOCAL_INPUT, "-s", addr, "-p", protocolStr,
155 "--sport", portStr, "-j", "RETURN", NULL);
156 res |= execIptables(target, op, LOCAL_OUTPUT, "-d", addr, "-p", protocolStr,
157 "--dport", portStr, "-j", "RETURN", NULL);
158 return res;
159}
160
161int FirewallController::setUidRule(int uid, FirewallRule rule) {
162 char uidStr[16];
163 sprintf(uidStr, "%d", uid);
164
165 const char* op;
Amith Yamasani390e4ea2015-04-25 19:08:57 -0700166 const char* target;
167 if (firewallType == WHITELIST) {
168 target = "RETURN";
169 op = (rule == ALLOW)? "-I" : "-D";
170 } else { // BLACKLIST mode
171 target = "DROP";
172 op = (rule == DENY)? "-I" : "-D";
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700173 }
174
175 int res = 0;
176 res |= execIptables(V4V6, op, LOCAL_INPUT, "-m", "owner", "--uid-owner", uidStr,
Amith Yamasani390e4ea2015-04-25 19:08:57 -0700177 "-j", target, NULL);
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700178 res |= execIptables(V4V6, op, LOCAL_OUTPUT, "-m", "owner", "--uid-owner", uidStr,
Amith Yamasani390e4ea2015-04-25 19:08:57 -0700179 "-j", target, NULL);
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700180 return res;
181}