blob: 11b4329ebcac69527005be6cc9d84c194287159e [file] [log] [blame]
// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "arc/network/manager.h"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdint.h>
#include <utility>
#include <base/bind.h>
#include <base/logging.h>
#include <base/message_loop/message_loop.h>
#include <base/strings/stringprintf.h>
#include <brillo/minijail/minijail.h>
#include "arc/network/ipc.pb.h"
namespace {
const char kUnprivilegedUser[] = "arc-networkd";
const uint64_t kManagerCapMask = CAP_TO_MASK(CAP_NET_RAW);
} // namespace
namespace arc_networkd {
Manager::Manager(std::unique_ptr<HelperProcess> ip_helper) {
ip_helper_ = std::move(ip_helper);
}
int Manager::OnInit() {
// Run with minimal privileges.
brillo::Minijail* m = brillo::Minijail::GetInstance();
struct minijail* jail = m->New();
// Most of these return void, but DropRoot() can fail if the user/group
// does not exist.
CHECK(m->DropRoot(jail, kUnprivilegedUser, kUnprivilegedUser))
<< "Could not drop root privileges";
m->UseCapabilities(jail, kManagerCapMask);
m->Enter(jail);
m->Destroy(jail);
// Handle subprocess lifecycle.
process_reaper_.Register(this);
CHECK(process_reaper_.WatchForChild(
FROM_HERE, ip_helper_->pid(),
base::Bind(&Manager::OnSubprocessExited, weak_factory_.GetWeakPtr(),
ip_helper_->pid())))
<< "Failed to watch child IpHelper process";
// Handle container lifecycle.
RegisterHandler(
SIGUSR1, base::Bind(&Manager::OnContainerStart, base::Unretained(this)));
RegisterHandler(
SIGUSR2, base::Bind(&Manager::OnContainerStop, base::Unretained(this)));
// Run after Daemon::OnInit().
base::MessageLoopForIO::current()->task_runner()->PostTask(
FROM_HERE,
base::Bind(&Manager::InitialSetup, weak_factory_.GetWeakPtr()));
return DBusDaemon::OnInit();
}
void Manager::InitialSetup() {
shill_client_ = std::make_unique<ShillClient>(std::move(bus_));
shill_client_->RegisterDevicesChangedHandler(
base::Bind(&Manager::OnDevicesChanged, weak_factory_.GetWeakPtr()));
device_mgr_ = std::make_unique<DeviceManager>(
base::Bind(&Manager::SendMessage, weak_factory_.GetWeakPtr()));
shill_client_->ScanDevices(
base::Bind(&Manager::OnDevicesChanged, weak_factory_.GetWeakPtr()));
}
bool Manager::OnContainerStart(const struct signalfd_siginfo& info) {
if (info.ssi_code == SI_USER) {
shill_client_->RegisterDefaultInterfaceChangedHandler(base::Bind(
&Manager::OnDefaultInterfaceChanged, weak_factory_.GetWeakPtr()));
}
// Stay registered.
return false;
}
bool Manager::OnContainerStop(const struct signalfd_siginfo& info) {
if (info.ssi_code == SI_USER) {
shill_client_->UnregisterDefaultInterfaceChangedHandler();
if (device_mgr_)
device_mgr_->DisableAll();
}
// Stay registered.
return false;
}
void Manager::OnDefaultInterfaceChanged(const std::string& ifname) {
LOG(INFO) << "Default interface changed to " << ifname;
if (device_mgr_)
device_mgr_->Enable(kAndroidDevice, ifname);
}
void Manager::OnDevicesChanged(const std::set<std::string>& devices) {
if (device_mgr_)
device_mgr_->Reset(devices);
}
void Manager::OnShutdown(int* exit_code) {
device_mgr_.reset();
}
void Manager::OnSubprocessExited(pid_t pid, const siginfo_t& info) {
LOG(ERROR) << "Subprocess " << pid << " exited unexpectedly";
Quit();
}
void Manager::SendMessage(const IpHelperMessage& msg) {
ip_helper_->SendMessage(msg);
}
} // namespace arc_networkd