blob: 935a417b26079b12c5b2bcca0ef3563a36bced02 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "patchpanel/proto_utils.h"
#include <net-base/byte_utils.h>
#include <net-base/http_url.h>
#include <net-base/ipv4_address.h>
#include <net-base/ipv6_address.h>
#include <net-base/network_config.h>
#include "patchpanel/arc_service.h"
#include "patchpanel/crostini_service.h"
namespace patchpanel {
void FillTerminaAllocationProto(
const CrostiniService::CrostiniDevice& termina_device,
TerminaVmStartupResponse* output) {
DCHECK(termina_device.lxd_ipv4_subnet());
DCHECK(termina_device.lxd_ipv4_address());
output->set_tap_device_ifname(termina_device.tap_device_ifname());
FillSubnetProto(termina_device.vm_ipv4_subnet(),
output->mutable_ipv4_subnet());
output->set_ipv4_address(termina_device.vm_ipv4_address().ToByteString());
output->set_gateway_ipv4_address(
termina_device.gateway_ipv4_address().ToByteString());
FillSubnetProto(*termina_device.lxd_ipv4_subnet(),
output->mutable_container_ipv4_subnet());
output->set_container_ipv4_address(
termina_device.lxd_ipv4_address()->ToByteString());
}
void FillParallelsAllocationProto(
const CrostiniService::CrostiniDevice& parallels_device,
ParallelsVmStartupResponse* output) {
output->set_tap_device_ifname(parallels_device.tap_device_ifname());
FillSubnetProto(parallels_device.vm_ipv4_subnet(),
output->mutable_ipv4_subnet());
output->set_ipv4_address(parallels_device.vm_ipv4_address().ToByteString());
}
void FillBruschettaAllocationProto(
const CrostiniService::CrostiniDevice& bruschetta_device,
BruschettaVmStartupResponse* output) {
output->set_tap_device_ifname(bruschetta_device.tap_device_ifname());
FillSubnetProto(bruschetta_device.vm_ipv4_subnet(),
output->mutable_ipv4_subnet());
output->set_ipv4_address(bruschetta_device.vm_ipv4_address().ToByteString());
output->set_gateway_ipv4_address(
bruschetta_device.gateway_ipv4_address().ToByteString());
}
void FillBorealisAllocationProto(
const CrostiniService::CrostiniDevice& borealis_device,
BorealisVmStartupResponse* output) {
output->set_tap_device_ifname(borealis_device.tap_device_ifname());
FillSubnetProto(borealis_device.vm_ipv4_subnet(),
output->mutable_ipv4_subnet());
output->set_ipv4_address(borealis_device.vm_ipv4_address().ToByteString());
output->set_gateway_ipv4_address(
borealis_device.gateway_ipv4_address().ToByteString());
}
void FillSubnetProto(const net_base::IPv4CIDR& cidr,
patchpanel::IPv4Subnet* output) {
output->set_addr(cidr.address().ToByteString());
output->set_base_addr(cidr.address().ToInAddr().s_addr);
output->set_prefix_len(static_cast<uint32_t>(cidr.prefix_length()));
}
void FillSubnetProto(const Subnet& virtual_subnet,
patchpanel::IPv4Subnet* output) {
FillSubnetProto(virtual_subnet.base_cidr(), output);
}
void FillArcDeviceDnsProxyProto(
const ArcService::ArcDevice& arc_device,
patchpanel::NetworkDevice* output,
const std::map<std::string, net_base::IPv4Address>& ipv4_addrs,
const std::map<std::string, net_base::IPv6Address>& ipv6_addrs) {
const auto& ipv4_it = ipv4_addrs.find(arc_device.bridge_ifname());
if (ipv4_it != ipv4_addrs.end()) {
output->set_dns_proxy_ipv4_addr(ipv4_it->second.ToByteString());
}
const auto& ipv6_it = ipv6_addrs.find(arc_device.bridge_ifname());
if (ipv6_it != ipv6_addrs.end()) {
output->set_dns_proxy_ipv6_addr(ipv6_it->second.ToByteString());
}
}
void FillDownstreamNetworkProto(
const DownstreamNetworkInfo& downstream_network_info,
patchpanel::DownstreamNetwork* output) {
output->set_downstream_ifname(downstream_network_info.downstream_ifname);
output->set_ipv4_gateway_addr(
downstream_network_info.ipv4_cidr.address().ToByteString());
FillSubnetProto(downstream_network_info.ipv4_cidr,
output->mutable_ipv4_subnet());
output->set_network_id(downstream_network_info.network_id);
}
void FillNetworkClientInfoProto(const DownstreamClientInfo& network_client_info,
NetworkClientInfo* output) {
output->set_mac_addr(net_base::byte_utils::ByteStringFromBytes(
network_client_info.mac_addr.ToBytes()));
output->set_ipv4_addr(network_client_info.ipv4_addr.ToByteString());
for (const auto& ipv6_addr : network_client_info.ipv6_addresses) {
output->add_ipv6_addresses(ipv6_addr.ToByteString());
}
output->set_hostname(network_client_info.hostname);
output->set_vendor_class(network_client_info.vendor_class);
}
net_base::NetworkConfig DeserializeNetworkConfig(
const patchpanel::NetworkConfig& in) {
net_base::NetworkConfig out;
if (in.has_ipv4_address()) {
out.ipv4_address = net_base::IPv4CIDR::CreateFromBytesAndPrefix(
in.ipv4_address().addr(), in.ipv4_address().prefix_len());
}
if (in.has_ipv4_broadcast()) {
out.ipv4_broadcast =
net_base::IPv4Address::CreateFromBytes(in.ipv4_broadcast());
}
if (in.has_ipv4_gateway()) {
out.ipv4_gateway =
net_base::IPv4Address::CreateFromBytes(in.ipv4_gateway());
}
for (const auto& ipv6_address : in.ipv6_addresses()) {
auto ipv6_addr_out = net_base::IPv6CIDR::CreateFromBytesAndPrefix(
ipv6_address.addr(), ipv6_address.prefix_len());
if (ipv6_addr_out) {
out.ipv6_addresses.push_back(*ipv6_addr_out);
}
}
if (in.has_ipv6_gateway()) {
out.ipv6_gateway =
net_base::IPv6Address::CreateFromBytes(in.ipv6_gateway());
}
out.ipv4_default_route = in.ipv4_default_route();
out.ipv6_blackhole_route = in.ipv6_blackhole_route();
for (const auto& prefix : in.excluded_route_prefixes()) {
auto prefix_out = net_base::IPCIDR::CreateFromBytesAndPrefix(
prefix.addr(), prefix.prefix_len());
if (prefix_out) {
out.excluded_route_prefixes.push_back(*prefix_out);
}
}
for (const auto& prefix : in.included_route_prefixes()) {
auto prefix_out = net_base::IPCIDR::CreateFromBytesAndPrefix(
prefix.addr(), prefix.prefix_len());
if (prefix_out) {
out.included_route_prefixes.push_back(*prefix_out);
}
}
for (const auto& route : in.rfc3442_routes()) {
auto prefix = net_base::IPv4CIDR::CreateFromBytesAndPrefix(
route.prefix().addr(), route.prefix().prefix_len());
auto gateway = net_base::IPv4Address::CreateFromBytes(route.gateway());
if (prefix && gateway) {
out.rfc3442_routes.emplace_back(*prefix, *gateway);
}
}
for (const auto& dns : in.dns_servers()) {
auto dns_out = net_base::IPAddress::CreateFromBytes(dns);
if (dns_out) {
out.dns_servers.push_back(*dns_out);
}
}
for (const auto& dnssl : in.dns_search_domains()) {
out.dns_search_domains.push_back(dnssl);
}
if (in.has_mtu()) {
out.mtu = in.mtu();
}
if (in.has_captive_portal_uri()) {
out.captive_portal_uri =
net_base::HttpUrl::CreateFromString(in.captive_portal_uri());
}
return out;
}
std::optional<ConnmarkUpdater::Conntrack5Tuple> GetConntrack5Tuple(
const SocketConnectionEvent& msg) {
const auto src_addr = net_base::IPAddress::CreateFromBytes(msg.saddr());
if (!src_addr.has_value()) {
LOG(ERROR) << __func__ << ": failed to convert source IP address.";
return std::nullopt;
}
const auto dst_addr = net_base::IPAddress::CreateFromBytes(msg.daddr());
if (!dst_addr.has_value()) {
LOG(ERROR) << __func__ << ": failed to convert destination IP address.";
return std::nullopt;
}
ConnmarkUpdater::IPProtocol proto;
switch (msg.proto()) {
case patchpanel::SocketConnectionEvent::IpProtocol::
SocketConnectionEvent_IpProtocol_TCP:
proto = ConnmarkUpdater::IPProtocol::kTCP;
break;
case patchpanel::SocketConnectionEvent::IpProtocol::
SocketConnectionEvent_IpProtocol_UDP:
proto = ConnmarkUpdater::IPProtocol::kUDP;
break;
default:
LOG(ERROR) << __func__ << ": invalid protocol: " << msg.proto();
return std::nullopt;
}
return ConnmarkUpdater::Conntrack5Tuple{
.src_addr = *src_addr,
.dst_addr = *dst_addr,
.sport = static_cast<uint16_t>(msg.sport()),
.dport = static_cast<uint16_t>(msg.dport()),
.proto = proto};
}
} // namespace patchpanel