1// 2// Copyright (C) 2015 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 "apmanager/dbus/firewalld_dbus_proxy.h" 18 19#include <base/bind.h> 20#include <brillo/errors/error.h> 21 22#include "apmanager/event_dispatcher.h" 23 24using std::string; 25 26namespace apmanager { 27 28FirewalldDBusProxy::FirewalldDBusProxy( 29 const scoped_refptr<dbus::Bus>& bus, 30 const base::Closure& service_appeared_callback, 31 const base::Closure& service_vanished_callback) 32 : proxy_(new org::chromium::FirewalldProxy(bus)), 33 dispatcher_(EventDispatcher::GetInstance()), 34 service_appeared_callback_(service_appeared_callback), 35 service_vanished_callback_(service_vanished_callback), 36 service_available_(false) { 37 // Monitor service owner changes. This callback lives for the lifetime of 38 // the ObjectProxy. 39 proxy_->GetObjectProxy()->SetNameOwnerChangedCallback( 40 base::Bind(&FirewalldDBusProxy::OnServiceOwnerChanged, 41 weak_factory_.GetWeakPtr())); 42 43 // One time callback when service becomes available. 44 proxy_->GetObjectProxy()->WaitForServiceToBeAvailable( 45 base::Bind(&FirewalldDBusProxy::OnServiceAvailable, 46 weak_factory_.GetWeakPtr())); 47} 48 49FirewalldDBusProxy::~FirewalldDBusProxy() {} 50 51bool FirewalldDBusProxy::RequestUdpPortAccess(const string& interface, 52 uint16_t port) { 53 if (!service_available_) { 54 LOG(ERROR) << "firewalld service not available"; 55 return false; 56 } 57 58 bool success = false; 59 brillo::ErrorPtr error; 60 if (!proxy_->PunchUdpHole(port, interface, &success, &error)) { 61 LOG(ERROR) << "Failed to request UDP port access: " 62 << error->GetCode() << " " << error->GetMessage(); 63 return false; 64 } 65 if (!success) { 66 LOG(ERROR) << "Access request for UDP port " << port 67 << " on interface " << interface << " is denied"; 68 return false; 69 } 70 LOG(INFO) << "Access granted for UDP port " << port 71 << " on interface " << interface; 72 return true; 73} 74 75bool FirewalldDBusProxy::ReleaseUdpPortAccess(const string& interface, 76 uint16_t port) { 77 if (!service_available_) { 78 LOG(ERROR) << "firewalld service not available"; 79 return false; 80 } 81 82 brillo::ErrorPtr error; 83 bool success; 84 if (!proxy_->PlugUdpHole(port, interface, &success, &error)) { 85 LOG(ERROR) << "Failed to release UDP port access: " 86 << error->GetCode() << " " << error->GetMessage(); 87 return false; 88 } 89 if (!success) { 90 LOG(ERROR) << "Release request for UDP port " << port 91 << " on interface " << interface << " is denied"; 92 return false; 93 } 94 LOG(INFO) << "Access released for UDP port " << port 95 << " on interface " << interface; 96 return true; 97} 98 99void FirewalldDBusProxy::OnServiceAvailable(bool available) { 100 LOG(INFO) << __func__ << ": " << available; 101 // The callback might invoke calls to the ObjectProxy, so defer the callback 102 // to event loop. 103 if (available && !service_appeared_callback_.is_null()) { 104 dispatcher_->PostTask(service_appeared_callback_); 105 } else if (!available && !service_vanished_callback_.is_null()) { 106 dispatcher_->PostTask(service_vanished_callback_); 107 } 108 service_available_ = available; 109} 110 111void FirewalldDBusProxy::OnServiceOwnerChanged(const string& old_owner, 112 const string& new_owner) { 113 LOG(INFO) << __func__ << " old: " << old_owner << " new: " << new_owner; 114 if (new_owner.empty()) { 115 OnServiceAvailable(false); 116 } else { 117 OnServiceAvailable(true); 118 } 119} 120 121} // namespace apmanager 122