| // Copyright 2016 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef PATCHPANEL_MANAGER_H_ | |
| #define PATCHPANEL_MANAGER_H_ | |
| #include <map> | |
| #include <memory> | |
| #include <optional> | |
| #include <set> | |
| #include <string> | |
| #include <utility> | |
| #include <vector> | |
| #include <base/files/scoped_file.h> | |
| #include <base/memory/weak_ptr.h> | |
| #include <chromeos/net-base/process_manager.h> | |
| #include <patchpanel/proto_bindings/patchpanel_service.pb.h> | |
| #include "patchpanel/address_manager.h" | |
| #include "patchpanel/arc_service.h" | |
| #include "patchpanel/clat_service.h" | |
| #include "patchpanel/counters_service.h" | |
| #include "patchpanel/crostini_service.h" | |
| #include "patchpanel/datapath.h" | |
| #include "patchpanel/dbus_client_notifier.h" | |
| #include "patchpanel/dhcp_server_controller.h" | |
| #include "patchpanel/downstream_network_info.h" | |
| #include "patchpanel/downstream_network_service.h" | |
| #include "patchpanel/forwarding_service.h" | |
| #include "patchpanel/guest_ipv6_service.h" | |
| #include "patchpanel/lifeline_fd_service.h" | |
| #include "patchpanel/multicast_counters_service.h" | |
| #include "patchpanel/multicast_forwarder.h" | |
| #include "patchpanel/multicast_metrics.h" | |
| #include "patchpanel/network_monitor_service.h" | |
| #include "patchpanel/routing_service.h" | |
| #include "patchpanel/rtnl_client.h" | |
| #include "patchpanel/shill_client.h" | |
| #include "patchpanel/subprocess_controller.h" | |
| #include "patchpanel/system.h" | |
| namespace patchpanel { | |
| class QoSService; | |
| // The core implementation of the patchpanel daemon. | |
| class Manager : public ForwardingService { | |
| public: | |
| // The caller should guarantee |system|, |process_manager|, |metrics| and | |
| // |client| variables outlive the created Manager instance. | |
| Manager(const base::FilePath& cmd_path, | |
| System* system, | |
| net_base::ProcessManager* process_manager, | |
| MetricsLibraryInterface* metrics, | |
| DbusClientNotifier* dbus_client_notifier, | |
| std::unique_ptr<ShillClient> shill_client, | |
| std::unique_ptr<RTNLClient> rtnl_client); | |
| Manager(const Manager&) = delete; | |
| Manager& operator=(const Manager&) = delete; | |
| virtual ~Manager(); | |
| // Queries the list of virtual devices managed by patchpanel. | |
| GetDevicesResponse GetDevices() const; | |
| // Handles notification indicating ARC++ is booting up. | |
| bool ArcStartup(pid_t pid); | |
| // Handles notification indicating ARC++ is spinning down. | |
| void ArcShutdown(); | |
| // Handles notification indicating ARCVM is booting up. | |
| std::optional<patchpanel::ArcVmStartupResponse> ArcVmStartup(uint32_t cid); | |
| // Handles notification indicating ARCVM is spinning down. | |
| void ArcVmShutdown(uint32_t cid); | |
| // Handles notification indicating a Termina VM is booting up. | |
| const CrostiniService::CrostiniDevice* const TerminaVmStartup(uint64_t vm_id); | |
| // Handles notification indicating a Termina VM is spinning down. | |
| void TerminaVmShutdown(uint64_t vm_id); | |
| // Handles notification indicating a Parallels VM is booting up. | |
| const CrostiniService::CrostiniDevice* const ParallelsVmStartup( | |
| uint64_t vm_id, uint32_t subnet_index); | |
| // Handles notification indicating a Parallels VM is spinning down. | |
| void ParallelsVmShutdown(uint64_t vm_id); | |
| // Handles notification indicating a Bruschetta VM is booting up. | |
| const CrostiniService::CrostiniDevice* const BruschettaVmStartup( | |
| uint64_t vm_id); | |
| // Handles notification indicating a Bruschetta VM is spinning down. | |
| void BruschettaVmShutdown(uint64_t vm_id); | |
| // Handles notification indicating a Borealis VM is booting up. | |
| const CrostiniService::CrostiniDevice* const BorealisVmStartup( | |
| uint64_t vm_id); | |
| // Handles notification indicating a Borealis VM is spinning down. | |
| void BorealisVmShutdown(uint64_t vm_id); | |
| // Connects and routes an existing network namespace created via minijail or | |
| // through rtnetlink RTM_NEWNSID. | |
| ConnectNamespaceResponse ConnectNamespace( | |
| const patchpanel::ConnectNamespaceRequest& request, | |
| base::ScopedFD client_fd); | |
| // Queries traffic counters. | |
| std::map<CountersService::CounterKey, CountersService::Counter> | |
| GetTrafficCounters(const std::set<std::string>& shill_devices) const; | |
| // Creates iptables rules requests from permission_broker. | |
| bool ModifyPortRule(const patchpanel::ModifyPortRuleRequest& request); | |
| // Starts or stops VPN lockdown. | |
| void SetVpnLockdown(bool enable_vpn_lockdown); | |
| // Creates iptables rules requests from dns-proxy. | |
| bool SetDnsRedirectionRule( | |
| const patchpanel::SetDnsRedirectionRuleRequest& request, | |
| base::ScopedFD client_fd); | |
| // Tags the socket pointed by |sock_fd| for routing and other purposes. | |
| bool TagSocket(const patchpanel::TagSocketRequest& request, | |
| const base::ScopedFD& sock_fd); | |
| // Start/Stop forwarding multicast traffic to ARC when ARC power state | |
| // changes. | |
| // When power state changes into interactive, start forwarding IPv4 and IPv6 | |
| // multicast mDNS and SSDP traffic for all non-WiFi interfaces, and for WiFi | |
| // interface only when Android WiFi multicast lock is held by any app in ARC. | |
| // When power state changes into non-interactive, stop forwarding multicast | |
| // traffic for all interfaces if enabled. | |
| void NotifyAndroidInteractiveState(bool is_interactive); | |
| // Start/Stop forwarding WiFi multicast traffic to and from ARC when Android | |
| // WiFi multicast lock held status changes. Start forwarding IPv4 and IPv6 | |
| // multicast mDNS and SSDP traffic for WiFi interfaces only when | |
| // device power state is interactive and Android WiFi multicast lock is held | |
| // by any app in ARC, otherwise stop multicast forwarder for ARC WiFi | |
| // interface. | |
| void NotifyAndroidWifiMulticastLockChange(bool is_held); | |
| // Apply changes based on the socket connection event. | |
| // Currently this is only used for ARC socket connections and applies QoS | |
| // setup and resets the QoS setup on connection closed. | |
| void NotifySocketConnectionEvent( | |
| const NotifySocketConnectionEventRequest& request); | |
| // Apply changes based on the socket connection event from ARC VPN. | |
| // Currently this is only used for ARC VPN traffic counting. | |
| void NotifyARCVPNSocketConnectionEvent( | |
| const NotifyARCVPNSocketConnectionEventRequest& request); | |
| // Set feature enabled flag. | |
| bool SetFeatureFlag(patchpanel::SetFeatureFlagRequest::FeatureFlag flag, | |
| bool enabled); | |
| void StartIPv6NDPForwarding( | |
| const ShillClient::Device& shill_device, | |
| std::string_view ifname_virtual, | |
| std::optional<int> mtu = std::nullopt, | |
| std::optional<int> hop_limit = std::nullopt) override; | |
| void StopIPv6NDPForwarding(const ShillClient::Device& shill_device, | |
| std::string_view ifname_virtual) override; | |
| void StartBroadcastForwarding(const ShillClient::Device& shill_device, | |
| std::string_view ifname_virtual) override; | |
| void StopBroadcastForwarding(const ShillClient::Device& shill_device, | |
| std::string_view ifname_virtual) override; | |
| void StartMulticastForwarding( | |
| const ShillClient::Device& shill_device, | |
| std::string_view ifname_virtual, | |
| MulticastForwarder::Direction dir = | |
| MulticastForwarder::Direction::kTwoWays) override; | |
| void StopMulticastForwarding( | |
| const ShillClient::Device& shill_device, | |
| std::string_view ifname_virtual, | |
| MulticastForwarder::Direction dir = | |
| MulticastForwarder::Direction::kTwoWays) override; | |
| DownstreamNetworkService* downstream_network_service() { | |
| return downstream_network_svc_.get(); | |
| } | |
| private: | |
| friend class ManagerTest; | |
| // The initialization tasks that are not necessary for handling dbus methods. | |
| void RunDelayedInitialization(); | |
| // Callbacks from |shill_client_|. | |
| void OnShillDefaultLogicalDeviceChanged( | |
| const ShillClient::Device* new_device, | |
| const ShillClient::Device* prev_device); | |
| void OnShillDefaultPhysicalDeviceChanged( | |
| const ShillClient::Device* new_device, | |
| const ShillClient::Device* prev_device); | |
| void OnShillDevicesChanged(const std::vector<ShillClient::Device>& added, | |
| const std::vector<ShillClient::Device>& removed); | |
| void OnIPConfigsChanged(const ShillClient::Device& shill_device); | |
| void OnIPv6NetworkChanged(const ShillClient::Device& shill_device); | |
| void OnDoHProvidersChanged(const ShillClient::DoHProviders& doh_providers); | |
| // Callback from |network_monitor_svc_|. | |
| void OnNeighborReachabilityEvent( | |
| int ifindex, | |
| const net_base::IPAddress& ip_addr, | |
| NeighborLinkMonitor::NeighborRole role, | |
| NeighborReachabilityEventSignal::EventType event_type); | |
| // Tears down a ConnectedNamespace setup given its connected namespace id. | |
| void OnConnectedNamespaceAutoclose(int connected_namespace_id); | |
| // Tears down a DNS redirection rule request given the lifeline fd value | |
| // committed by the client dns-proxy instance. | |
| void OnDnsRedirectionRulesAutoclose(int lifeline_fd); | |
| const CrostiniService::CrostiniDevice* StartCrosVm( | |
| uint64_t vm_id, | |
| CrostiniService::VMType vm_type, | |
| uint32_t subnet_index = kAnySubnetIndex); | |
| void StopCrosVm(uint64_t vm_id, CrostiniService::VMType vm_type); | |
| std::vector<DownstreamClientInfo> GetDownstreamClientInfo( | |
| std::string_view downstream_ifname) const; | |
| // Disable and re-enable IPv6 inside a namespace. | |
| void RestartIPv6(std::string_view netns_name); | |
| // Dispatch |msg| to child processes. | |
| void SendGuestMessage(const GuestMessage& msg); | |
| // Owned by PatchpanelDaemon. | |
| System* system_; | |
| // UMA metrics client. Owned by PatchpanelDaemon. | |
| MetricsLibraryInterface* metrics_; | |
| // The client of the Manager. | |
| DbusClientNotifier* dbus_client_notifier_; | |
| // Shill Dbus client. | |
| std::unique_ptr<ShillClient> shill_client_; | |
| // rtnetlink client. | |
| std::unique_ptr<RTNLClient> rtnl_client_; | |
| // High level routing and iptables controller service. | |
| std::unique_ptr<Datapath> datapath_; | |
| // Routing service. | |
| std::unique_ptr<RoutingService> routing_svc_; | |
| // ARC++/ARCVM service. | |
| std::unique_ptr<ArcService> arc_svc_; | |
| // Crostini and other VM service. | |
| std::unique_ptr<CrostiniService> cros_svc_; | |
| // adb connection forwarder service. | |
| std::unique_ptr<SubprocessController> adb_proxy_; | |
| // IPv4 and IPv6 Multicast forwarder service. | |
| std::unique_ptr<SubprocessController> mcast_proxy_; | |
| // IPv6 neighbor discovery forwarder process handler. | |
| std::unique_ptr<SubprocessController> nd_proxy_; | |
| // Socket service process handler. | |
| std::unique_ptr<SubprocessController> socket_service_; | |
| // IPv6 address provisioning / ndp forwarding service. | |
| std::unique_ptr<GuestIPv6Service> ipv6_svc_; | |
| // CLAT service. | |
| std::unique_ptr<ClatService> clat_svc_; | |
| // Traffic counter service. | |
| std::unique_ptr<CountersService> counters_svc_; | |
| // Multicast packet counter service. | |
| std::unique_ptr<MulticastCountersService> multicast_counters_svc_; | |
| // L2 neighbor monitor service. | |
| std::unique_ptr<NetworkMonitorService> network_monitor_svc_; | |
| // QoS service. | |
| std::unique_ptr<QoSService> qos_svc_; | |
| // LifelineFD management service | |
| std::unique_ptr<LifelineFDService> lifeline_fd_svc_; | |
| // TetheredNetwork and LocalOnlyNetwork management service. | |
| std::unique_ptr<DownstreamNetworkService> downstream_network_svc_; | |
| // IPv4 prefix and address manager. | |
| AddressManager addr_mgr_; | |
| // All namespaces currently connected through patchpanel ConnectNamespace | |
| // API, keyed by the the namespace id of the ConnectedNamespace. | |
| std::map<int, ConnectedNamespace> connected_namespaces_; | |
| int connected_namespaces_next_id_{0}; | |
| // DNS proxy's IPv4 and IPv6 addresses keyed by its guest interface. | |
| std::map<std::string, net_base::IPv4Address> dns_proxy_ipv4_addrs_; | |
| std::map<std::string, net_base::IPv6Address> dns_proxy_ipv6_addrs_; | |
| // All rules currently created through patchpanel RedirectDns | |
| // API, keyed by the host-side interface name of the ConnectedNamespace of the | |
| // target dns-proxy instance to which the queries should be redirected. | |
| std::map<int, DnsRedirectionRule> dns_redirection_rules_; | |
| // Fetches and reports multicast packet count to UMA metrics. | |
| std::unique_ptr<MulticastMetrics> multicast_metrics_; | |
| base::WeakPtrFactory<Manager> weak_factory_{this}; | |
| }; | |
| } // namespace patchpanel | |
| #endif // PATCHPANEL_MANAGER_H_ |