blob: b40adc490f55b5070759845acf0839739fbddb40 [file] [log] [blame]
// Copyright 2020 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 "patchpanel/routing_service.h"
#include <iostream>
#include <base/logging.h>
namespace patchpanel {
RoutingService::RoutingService() {}
int RoutingService::GetSockopt(
int sockfd, int level, int optname, void* optval, socklen_t* optlen) {
return getsockopt(sockfd, level, optname, optval, optlen);
}
int RoutingService::SetSockopt(
int sockfd, int level, int optname, const void* optval, socklen_t optlen) {
return setsockopt(sockfd, level, optname, optval, optlen);
}
bool RoutingService::SetFwmark(int sockfd, Fwmark mark, Fwmark mask) {
uint32_t fwmark_value = 0;
socklen_t fwmark_len = sizeof(fwmark_value);
if (GetSockopt(sockfd, SOL_SOCKET, SO_MARK, &fwmark_value, &fwmark_len) < 0) {
PLOG(ERROR) << "SetFwmark mark=" << mark.ToString()
<< " mask=" << mask.ToString()
<< " getsockopt SOL_SOCKET SO_MARK failed";
return false;
}
fwmark_value = (mark & mask).Value() | (fwmark_value & ~mask.Value());
fwmark_len = sizeof(fwmark_value);
if (SetSockopt(sockfd, SOL_SOCKET, SO_MARK, &fwmark_value, fwmark_len) < 0) {
PLOG(ERROR) << "SetFwmark mark=" << mark.ToString()
<< " mask=" << mask.ToString()
<< " setsockopt SOL_SOCKET SO_MARK failed";
return false;
}
return true;
}
bool RoutingService::SetVpnFwmark(
int sockfd, patchpanel::SetVpnIntentRequest::VpnRoutingPolicy policy) {
Fwmark mark = {};
switch (policy) {
case patchpanel::SetVpnIntentRequest::DEFAULT_ROUTING:
break;
case patchpanel::SetVpnIntentRequest::ROUTE_ON_VPN:
mark = kFwmarkRouteOnVpn;
break;
case patchpanel::SetVpnIntentRequest::BYPASS_VPN:
mark = kFwmarkBypassVpn;
break;
default:
LOG(ERROR) << "Incorrect SetVpnIntent policy value " << policy;
return false;
}
LOG(INFO) << "SetFwmark mark=" << mark.ToString()
<< " mask=" << kFwmarkVpnMask.ToString()
<< " getsockopt SOL_SOCKET SO_MARK";
return SetFwmark(sockfd, mark, kFwmarkVpnMask);
}
const std::string& TrafficSourceName(TrafficSource source) {
static std::map<TrafficSource, std::string> kTrafficSourceNames = {
{CHROME, "CHROME"},
{USER, "USER"},
{UPDATE_ENGINE, "UPDATE_ENGINE"},
{SYSTEM, "SYSTEM"},
{HOST_VPN, "HOST_VPN"},
{ARC, "ARC"},
{CROSVM, "CROSVM"},
{PLUGINVM, "PLUGINVM"},
{TETHER_DOWNSTREAM, "TETHER_DOWNSTREAM"},
{ARC_VPN, "ARC_VPN"},
{UNKNOWN, "UNKNOWN"},
};
const auto& it = kTrafficSourceNames.find(source);
if (it == kTrafficSourceNames.end()) {
return kTrafficSourceNames.find(UNKNOWN)->second;
}
return it->second;
}
std::ostream& operator<<(std::ostream& stream, const LocalSourceSpecs& source) {
return stream << "{source: " << TrafficSourceName(source.source_type)
<< ", uid: " << (source.uid_name ? source.uid_name : "")
<< ", classid: " << source.classid
<< ", is_on_vpn: " << (source.is_on_vpn ? "true" : "false")
<< "}";
}
} // namespace patchpanel