1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_CROSTINI_CROSTINI_PORT_FORWARDER_H_
#define CHROME_BROWSER_ASH_CROSTINI_CROSTINI_PORT_FORWARDER_H_
#include <string>
#include <unordered_map>
#include "base/files/scoped_file.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/values.h"
#include "chrome/browser/ash/crostini/crostini_util.h"
#include "components/keyed_service/core/keyed_service.h"
class Profile;
namespace crostini {
extern const char kDefaultInterfaceToForward[];
extern const char kWlanInterface[];
extern const char kPortNumberKey[];
extern const char kPortProtocolKey[];
extern const char kPortInterfaceKey[];
extern const char kPortLabelKey[];
extern const char kPortVmNameKey[];
extern const char kPortContainerNameKey[];
class CrostiniPortForwarder : public KeyedService {
public:
class Observer : public base::CheckedObserver {
public:
// Called when a port's active state changes.
virtual void OnActivePortsChanged(const base::Value::List& activePorts) = 0;
virtual void OnActiveNetworkChanged(const base::Value& interface,
const base::Value& ipAddress) = 0;
};
enum class Protocol {
TCP = 0,
UDP = 1,
};
struct PortRuleKey {
uint16_t port_number;
Protocol protocol_type;
guest_os::GuestId container_id;
bool operator==(const PortRuleKey& other) const {
return port_number == other.port_number &&
protocol_type == other.protocol_type;
}
};
// Helper for using PortRuleKey as key entries in std::unordered_maps.
struct PortRuleKeyHasher {
std::size_t operator()(const PortRuleKey& k) const {
return ((std::hash<uint16_t>()(k.port_number) ^
(std::hash<Protocol>()(k.protocol_type) << 1)) >>
1);
}
};
using ResultCallback = base::OnceCallback<void(bool)>;
void AddObserver(Observer* observer) { observers_.AddObserver(observer); }
void RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
// The result_callback will only be called with success=true IF all conditions
// pass. This means a port setting has been successfully updated in the
// iptables and the profile preference setting has also been successfully
// updated.
void ActivatePort(const guest_os::GuestId& container_id,
uint16_t port_number,
const Protocol& protocol_type,
ResultCallback result_callback);
void AddPort(const guest_os::GuestId& container_id,
uint16_t port_number,
const Protocol& protocol_type,
const std::string& label,
ResultCallback result_callback);
void DeactivatePort(const guest_os::GuestId& container_id,
uint16_t port_number,
const Protocol& protocol_type,
ResultCallback result_callback);
void RemovePort(const guest_os::GuestId& container_id,
uint16_t port_number,
const Protocol& protocol_type,
ResultCallback result_callback);
// TODO(matterchen): For the two following methods, implement callback
// results.
// Deactivate all ports belonging to the container_id and removes them from
// the preferences.
void RemoveAllPorts(const guest_os::GuestId& container_id);
// Deactivate all active ports belonging to the container_id and set their
// preference to inactive such that these ports will not be automatically
// re-forwarded on re-startup. This is called on container shutdown.
void DeactivateAllActivePorts(const guest_os::GuestId& container_id);
base::Value::List GetActivePorts();
base::Value::List GetActiveNetworkInfo();
size_t GetNumberOfForwardedPortsForTesting();
std::optional<base::Value> ReadPortPreferenceForTesting(
const PortRuleKey& key);
void ActiveNetworksChanged(const std::string& interface,
const std::string& ip_address);
explicit CrostiniPortForwarder(Profile* profile);
CrostiniPortForwarder(const CrostiniPortForwarder&) = delete;
CrostiniPortForwarder& operator=(const CrostiniPortForwarder&) = delete;
~CrostiniPortForwarder() override;
private:
FRIEND_TEST_ALL_PREFIXES(CrostiniPortForwarderTest,
TryActivatePortPermissionBrokerClientFail);
FRIEND_TEST_ALL_PREFIXES(CrostiniPortForwarderTest, GetActivePortsForUI);
void SignalActivePortsChanged();
bool MatchPortRuleDict(const base::Value& dict, const PortRuleKey& key);
bool MatchPortRuleContainerId(const base::Value& dict,
const guest_os::GuestId& container_id);
void AddNewPortPreference(const PortRuleKey& key, const std::string& label);
bool RemovePortPreference(const PortRuleKey& key);
std::optional<base::Value> ReadPortPreference(const PortRuleKey& key);
void OnActivatePortCompleted(ResultCallback result_callback,
PortRuleKey key,
bool success);
void OnRemoveOrDeactivatePortCompleted(ResultCallback result_callback,
PortRuleKey key,
bool success);
void TryDeactivatePort(const PortRuleKey& key,
const guest_os::GuestId& container_id,
base::OnceCallback<void(bool)> result_callback);
void TryActivatePort(const PortRuleKey& key,
const guest_os::GuestId& container_id,
base::OnceCallback<void(bool)> result_callback);
void UpdateActivePortInterfaces();
// For each port rule (protocol, port, interface), keep track of the fd which
// requested it so we can release it on removal / deactivate.
std::unordered_map<PortRuleKey, base::ScopedFD, PortRuleKeyHasher>
forwarded_ports_;
// Current interface to forward ports on.
std::string current_interface_;
std::string ip_address_;
base::ObserverList<Observer> observers_;
raw_ptr<Profile> profile_;
base::WeakPtrFactory<CrostiniPortForwarder> weak_ptr_factory_{this};
}; // class
} // namespace crostini
#endif // CHROME_BROWSER_ASH_CROSTINI_CROSTINI_PORT_FORWARDER_H_
|