blob: 994dcc83b7d9903382a5d76b4bb5a3eb7ee70383 [file] [log] [blame]
Hugo Benichi7d9d8db2020-03-30 15:56:56 +09001// Copyright 2020 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Garrick Evans3388a032020-03-24 11:25:55 +09005#include "patchpanel/routing_service.h"
Hugo Benichi7d9d8db2020-03-30 15:56:56 +09006
7#include <iostream>
8
9#include <base/logging.h>
10
11namespace {
12// TODO(hugobenichi) Formalize the semantics of fwmark bits with a bitfield
13// struct.
14constexpr const uint32_t kFwmarkRouteOnVpnBit = 0x80000000; // 1st MSB
15constexpr const uint32_t kFwmarkBypassVpnBit = 0x40000000; // 2nd MSB
16constexpr const uint32_t kFwmarkVpnMask =
17 kFwmarkBypassVpnBit | kFwmarkRouteOnVpnBit;
18} // namespace
19
Garrick Evans3388a032020-03-24 11:25:55 +090020namespace patchpanel {
Hugo Benichi7d9d8db2020-03-30 15:56:56 +090021
22RoutingService::RoutingService() {}
23
24int RoutingService::GetSockopt(
25 int sockfd, int level, int optname, void* optval, socklen_t* optlen) {
26 return getsockopt(sockfd, level, optname, optval, optlen);
27}
28
29int RoutingService::SetSockopt(
30 int sockfd, int level, int optname, const void* optval, socklen_t optlen) {
31 return setsockopt(sockfd, level, optname, optval, optlen);
32}
33
34bool RoutingService::SetFwmark(int sockfd, uint32_t mark, uint32_t mask) {
35 uint32_t fwmark_value = 0;
36 socklen_t fwmark_len = sizeof(fwmark_value);
37 if (GetSockopt(sockfd, SOL_SOCKET, SO_MARK, &fwmark_value, &fwmark_len) < 0) {
38 PLOG(ERROR) << "SetFwmark mark=0x" << std::hex << mark << " mask=0x"
39 << std::hex << mask << " getsockopt SOL_SOCKET SO_MARK failed";
40 return false;
41 }
42
43 fwmark_value = (mark & mask) | (fwmark_value & ~mask);
44
45 fwmark_len = sizeof(fwmark_value);
46 if (SetSockopt(sockfd, SOL_SOCKET, SO_MARK, &fwmark_value, fwmark_len) < 0) {
47 PLOG(ERROR) << "SetFwmark mark=0x" << std::hex << mark << " mask=0x"
48 << std::hex << mask << " setsockopt SOL_SOCKET SO_MARK failed";
49 return false;
50 }
51
52 return true;
53}
54
55bool RoutingService::SetVpnFwmark(
56 int sockfd, patchpanel::SetVpnIntentRequest::VpnRoutingPolicy policy) {
57 uint32_t mark;
58 switch (policy) {
59 case patchpanel::SetVpnIntentRequest::DEFAULT_ROUTING:
60 mark = 0;
61 break;
62 case patchpanel::SetVpnIntentRequest::ROUTE_ON_VPN:
63 mark = kFwmarkRouteOnVpnBit;
64 break;
65 case patchpanel::SetVpnIntentRequest::BYPASS_VPN:
66 mark = kFwmarkBypassVpnBit;
67 break;
68 default:
69 LOG(ERROR) << "Incorrect SetVpnIntent policy value " << policy;
70 return false;
71 }
72 return SetFwmark(sockfd, mark, kFwmarkVpnMask);
73}
74
Garrick Evans3388a032020-03-24 11:25:55 +090075} // namespace patchpanel