Publish a binder interface

This should have the same functionality as the DBus interface. It should
also be perfectly safe to use both.

Change-Id: I42945941cb6e87d4fbee4797cb3d2286bcaa0267
Test: webservd can still open its ports via firewalld
Bug: 25932807
diff --git a/Android.mk b/Android.mk
index 7b4f06d..904ae52 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,13 +21,17 @@
   LOCAL_CPP_EXTENSION := .cc
   LOCAL_CLANG := true
   LOCAL_SHARED_LIBRARIES += \
+      libbinder \
+      libbinderwrapper \
       libbrillo \
+      libbrillo-binder \
       libbrillo-dbus \
       libbrillo-minijail \
       libchrome \
       libchrome-dbus \
       libdbus \
-      libminijail
+      libminijail \
+      libutils
   LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
   LOCAL_CPPFLAGS += -Wno-sign-promo
 endef
@@ -47,6 +51,8 @@
 LOCAL_SRC_FILES := \
     dbus_bindings/dbus-service-config.json \
     dbus_bindings/org.chromium.Firewalld.dbus-xml \
+    binder_bindings/android/firewalld/IFirewall.aidl \
+    binder_interface.cc \
     firewall_daemon.cc \
     firewall_service.cc \
     iptables.cc
diff --git a/binder_bindings/android/firewalld/IFirewall.aidl b/binder_bindings/android/firewalld/IFirewall.aidl
new file mode 100644
index 0000000..45c58c4
--- /dev/null
+++ b/binder_bindings/android/firewalld/IFirewall.aidl
@@ -0,0 +1,25 @@
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android.firewalld;
+
+@utf8InCpp
+interface IFirewall {
+  void PunchTcpHole(int port, String iface);
+  void PunchUdpHole(int port, String iface);
+  void PlugTcpHole(int port, String iface);
+  void PlugUdpHole(int port, String iface);
+  void RequestVpnSetup(in String[] usernames, String iface);
+  void RemoveVpnSetup(in String[] usernames, String iface);
+}
diff --git a/binder_interface.cc b/binder_interface.cc
new file mode 100644
index 0000000..6205770
--- /dev/null
+++ b/binder_interface.cc
@@ -0,0 +1,78 @@
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "binder_interface.h"
+#include "iptables.h"
+
+using android::binder::Status;
+
+using std::string;
+using std::vector;
+
+namespace firewalld {
+
+BinderInterface::BinderInterface(IpTables* service)
+    : service_(service) {}
+
+Status BinderInterface::PunchTcpHole(int32_t port, const string& iface) {
+  if (service_->PunchTcpHole(port, iface)) {
+    return Status::ok();
+  }
+
+  return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+}
+
+Status BinderInterface::PunchUdpHole(int32_t port, const string& iface) {
+  if (service_->PunchUdpHole(port, iface)) {
+    return Status::ok();
+  }
+
+  return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+}
+
+Status BinderInterface::PlugTcpHole(int32_t port, const string& iface) {
+  if (service_->PlugTcpHole(port, iface)) {
+    return Status::ok();
+  }
+
+  return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+}
+
+Status BinderInterface::PlugUdpHole(int32_t port, const string& iface) {
+  if (service_->PlugUdpHole(port, iface)) {
+    return Status::ok();
+  }
+
+  return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+}
+
+Status BinderInterface::RequestVpnSetup(const vector<string>& usernames,
+                                        const string& iface) {
+  if (service_->RequestVpnSetup(usernames, iface)) {
+    return Status::ok();
+  }
+
+  return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+}
+
+Status BinderInterface::RemoveVpnSetup(const vector<string>& usernames,
+                                       const string& iface) {
+  if (service_->RemoveVpnSetup(usernames, iface)) {
+    return Status::ok();
+  }
+
+  return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+}
+
+}  // namespace firewalld
diff --git a/binder_interface.h b/binder_interface.h
new file mode 100644
index 0000000..17ec690
--- /dev/null
+++ b/binder_interface.h
@@ -0,0 +1,51 @@
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef FIREWALLD_BINDER_INTERFACE_H_
+#define FIREWALLD_BINDER_INTERFACE_H_
+
+#include <android/firewalld/BnFirewall.h>
+
+namespace firewalld {
+
+class IpTables;
+class BinderInterface : public android::firewalld::BnFirewall {
+ public:
+  explicit BinderInterface(IpTables* service);
+  virtual ~BinderInterface() = default;
+
+  android::binder::Status PunchTcpHole(int32_t port, const std::string& iface)
+      override;
+  android::binder::Status PunchUdpHole(int32_t port, const std::string& iface)
+      override;
+  android::binder::Status PlugTcpHole(int32_t port, const std::string& iface)
+      override;
+  android::binder::Status PlugUdpHole(int32_t port, const std::string& iface)
+      override;
+  android::binder::Status RequestVpnSetup(
+      const std::vector<std::string>& usernames,
+      const std::string& iface) override;
+  android::binder::Status RemoveVpnSetup(
+      const std::vector<std::string>& usernames,
+      const std::string& iface) override;
+
+ private:
+  IpTables* service_;
+
+  DISALLOW_COPY_AND_ASSIGN(BinderInterface);
+};
+
+}  // namespace firewalld
+
+#endif /* FIREWALLD_BINDER_INTERFACE_H_ */
diff --git a/firewall_daemon.cc b/firewall_daemon.cc
index 4c5a037..ae12e5a 100644
--- a/firewall_daemon.cc
+++ b/firewall_daemon.cc
@@ -18,8 +18,17 @@
 
 #include <base/logging.h>
 
+#ifdef __ANDROID__
+#include <sysexits.h>
+#include <binderwrapper/binder_wrapper.h>
+#endif  // __ANDROID__
+
 namespace firewalld {
 
+#ifdef __ANDROID__
+const char kServiceName[] = "android.firewalld.Firewall";
+#endif  // __ANDROID__
+
 FirewallDaemon::FirewallDaemon()
     : brillo::DBusServiceDaemon{kFirewallServiceName,
                                 dbus::ObjectPath{kFirewallServicePath}} {
@@ -30,6 +39,21 @@
       new firewalld::FirewallService{object_manager_.get()});
   firewall_service_->RegisterAsync(
       sequencer->GetHandler("Service.RegisterAsync() failed.", true));
+
+#ifdef __ANDROID__
+  android::BinderWrapper::Create();
+  if (!binder_watcher_.Init()) {
+    LOG(ERROR) << "Could not initialize binder watcher.";
+    return;
+  }
+
+  if (!android::BinderWrapper::Get()->RegisterService(
+           kServiceName,
+           firewall_service_->GetBinderInterface())) {
+    LOG(ERROR) << "Could not register service " << kServiceName << ".";
+  }
+#endif  // __ANDROID__
+
 }
 
 }  // namespace firewalld
diff --git a/firewall_daemon.h b/firewall_daemon.h
index d82b79d..89ed4ad 100644
--- a/firewall_daemon.h
+++ b/firewall_daemon.h
@@ -19,6 +19,10 @@
 #include <brillo/daemons/dbus_daemon.h>
 #include <brillo/dbus/async_event_sequencer.h>
 
+#ifdef __ANDROID__
+#include <brillo/binder_watcher.h>
+#endif  // __ANDROID__
+
 #include "dbus_interface.h"
 #include "firewall_service.h"
 
@@ -34,6 +38,9 @@
   void RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) override;
 
  private:
+#ifdef __ANDROID__
+  brillo::BinderWatcher binder_watcher_;
+#endif  // __ANDROID__
   std::unique_ptr<FirewallService> firewall_service_;
 
   DISALLOW_COPY_AND_ASSIGN(FirewallDaemon);
diff --git a/firewall_service.cc b/firewall_service.cc
index 4cf3260..b339e96 100644
--- a/firewall_service.cc
+++ b/firewall_service.cc
@@ -42,6 +42,18 @@
   dbus_object_.RegisterAsync(callback);
 }
 
+#ifdef __ANDROID__
+  // Get the binder interface for this service
+android::sp<BinderInterface> FirewallService::GetBinderInterface() {
+  if (!binder_interface_.get()) {
+    binder_interface_ =
+        android::sp<BinderInterface>(new BinderInterface(&iptables_));
+  }
+
+  return binder_interface_;
+}
+#endif  // __ANDROID__
+
 #if !defined(__ANDROID__)
 void FirewallService::OnPermissionBrokerRemoved(const dbus::ObjectPath& path) {
   LOG(INFO) << "permission_broker died, plugging all firewall holes";
diff --git a/firewall_service.h b/firewall_service.h
index 6d46255..2cf5218 100644
--- a/firewall_service.h
+++ b/firewall_service.h
@@ -26,6 +26,10 @@
 # include "permission_broker/dbus-proxies.h"
 #endif  // __ANDROID__
 
+#ifdef __ANDROID__
+#include "binder_interface.h"
+#endif  // __ANDROID__
+
 #include "iptables.h"
 
 using CompletionAction =
@@ -42,6 +46,11 @@
   // Connects to D-Bus system bus and exports methods.
   void RegisterAsync(const CompletionAction& callback);
 
+#ifdef __ANDROID__
+  // Get the binder interface for this firewall.
+  android::sp<BinderInterface> GetBinderInterface();
+#endif  // __ANDROID__
+
  private:
 #if !defined(__ANDROID__)
   void OnPermissionBrokerRemoved(const dbus::ObjectPath& path);
@@ -54,6 +63,11 @@
 #endif  // __ANDROID__
   IpTables iptables_;
 
+#ifdef __ANDROID__
+  // A binder interface for this firewall.
+  android::sp<BinderInterface> binder_interface_;
+#endif  // __ANDROID__
+
   base::WeakPtrFactory<FirewallService> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(FirewallService);
 };