iptables.cc revision 8620868c44d58dc0632df3a7be7c48be1eb2421b
1// Copyright 2014 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "firewalld/iptables.h" 6 7#include <string> 8#include <vector> 9 10#include <base/logging.h> 11#include <base/strings/stringprintf.h> 12#include <chromeos/process.h> 13 14namespace { 15const char kIptablesPath[] = "/sbin/iptables"; 16} 17 18namespace firewalld { 19 20IpTables::IpTables() : IpTables{kIptablesPath} {} 21 22IpTables::IpTables(const std::string& path) : executable_path_{path} {} 23 24bool IpTables::PunchHole(chromeos::ErrorPtr* error, 25 uint16_t in_port, 26 bool* out_success) { 27 *out_success = false; 28 29 if (in_port == 0) { 30 // Port 0 is not a valid TCP/UDP port. 31 *out_success = false; 32 return true; 33 } 34 35 if (tcp_holes_.find(in_port) != tcp_holes_.end()) { 36 // We have already punched a hole for |in_port|. 37 // Be idempotent: do nothing and succeed. 38 *out_success = true; 39 return true; 40 } 41 42 LOG(INFO) << "Punching hole for port " << in_port; 43 if (!IpTables::AddAllowRule(executable_path_, in_port)) { 44 // If the 'iptables' command fails, this method fails. 45 LOG(ERROR) << "Calling 'iptables' failed"; 46 *out_success = false; 47 return true; 48 } 49 50 // Track the hole we just punched. 51 tcp_holes_.insert(in_port); 52 53 *out_success = true; 54 return true; 55} 56 57bool IpTables::PlugHole(chromeos::ErrorPtr* error, 58 uint16_t in_port, 59 bool* out_success) { 60 *out_success = false; 61 62 if (in_port == 0) { 63 // Port 0 is not a valid TCP/UDP port. 64 *out_success = false; 65 return true; 66 } 67 68 if (tcp_holes_.find(in_port) == tcp_holes_.end()) { 69 // There is no firewall hole for |in_port|. 70 // Even though this makes |PlugHole| not idempotent, 71 // and Punch/Plug not entirely symmetrical, fail. It might help catch bugs. 72 *out_success = false; 73 return true; 74 } 75 76 LOG(INFO) << "Plugging hole for port " << in_port; 77 if (!IpTables::DeleteAllowRule(executable_path_, in_port)) { 78 // If the 'iptables' command fails, this method fails. 79 LOG(ERROR) << "Calling 'iptables' failed"; 80 *out_success = false; 81 return true; 82 } 83 84 // Stop tracking the hole we just plugged. 85 tcp_holes_.erase(in_port); 86 87 *out_success = true; 88 return true; 89} 90 91// static 92bool IpTables::AddAllowRule(const std::string& path, uint16_t port) { 93 chromeos::ProcessImpl iptables; 94 iptables.AddArg(path); 95 iptables.AddArg("-A"); // append 96 iptables.AddArg("INPUT"); 97 iptables.AddArg("-p"); // protocol 98 iptables.AddArg("tcp"); 99 iptables.AddArg("--dport"); // destination port 100 std::string port_number = base::StringPrintf("%d", port); 101 iptables.AddArg(port_number.c_str()); 102 iptables.AddArg("-j"); 103 iptables.AddArg("ACCEPT"); 104 105 return iptables.Run() == 0; 106} 107 108// static 109bool IpTables::DeleteAllowRule(const std::string& path, uint16_t port) { 110 chromeos::ProcessImpl iptables; 111 iptables.AddArg(path); 112 iptables.AddArg("-D"); // delete 113 iptables.AddArg("INPUT"); 114 iptables.AddArg("-p"); // protocol 115 iptables.AddArg("tcp"); 116 iptables.AddArg("--dport"); // destination port 117 std::string port_number = base::StringPrintf("%d", port); 118 iptables.AddArg(port_number.c_str()); 119 iptables.AddArg("-j"); 120 iptables.AddArg("ACCEPT"); 121 122 return iptables.Run() == 0; 123} 124 125} // namespace firewalld 126