blob: f91f9f748877c9e1e2e57ad0678a11065da335ee [file] [log] [blame]
Hugo Benichif818c782021-04-10 00:09:50 +09001// Copyright 2021 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
5#include "patchpanel/system.h"
6
Hugo Benichi153c7112021-02-22 17:46:33 +09007#include <fcntl.h>
8#include <sys/stat.h>
Hugo Benichi96ee6f62021-06-28 14:07:20 +09009#include <sys/wait.h>
Hugo Benichi153c7112021-02-22 17:46:33 +090010#include <unistd.h>
11
12#include <base/files/scoped_file.h>
13
Hugo Benichif818c782021-04-10 00:09:50 +090014namespace patchpanel {
15
Hugo Benichi153c7112021-02-22 17:46:33 +090016namespace {
17
18// /proc/sys/ paths and fragments used for System::SysNetSet
19// Defines the local port range that is used by TCP and UDP traffic to choose
20// the local port (IPv4 and IPv6).
21constexpr const char kSysNetIPLocalPortRangePath[] =
22 "/proc/sys/net/ipv4/ip_local_port_range";
23// Enables/Disables IPv4 forwarding between interfaces.
24constexpr const char kSysNetIPv4ForwardingPath[] =
25 "/proc/sys/net/ipv4/ip_forward";
26// /proc/sys path for controlling connection tracking helper modules
27constexpr const char kSysNetConntrackHelperPath[] =
28 "/proc/sys/net/netfilter/nf_conntrack_helper";
29// Prefix for IPv4 interface configuration.
30constexpr const char kSysNetIPv4ConfPrefix[] = "/proc/sys/net/ipv4/conf/";
31// Suffix for allowing localhost as a source or destination when routing IPv4.
32constexpr const char kSysNetIPv4RouteLocalnetSuffix[] = "/route_localnet";
33// Enables/Disables IPv6 forwarding between interfaces.
34constexpr const char kSysNetIPv6ForwardingPath[] =
35 "/proc/sys/net/ipv6/conf/all/forwarding";
36// Prefix for IPv6 interface configuration.
37constexpr const char kSysNetIPv6ConfPrefix[] = "/proc/sys/net/ipv6/conf/";
38// Suffix for accepting Router Advertisements on an interface and
39// autoconfiguring it with IPv6 parameters.
40constexpr const char kSysNetIPv6AcceptRaSuffix[] = "/accept_ra";
41
42} // namespace
43
Hugo Benichif818c782021-04-10 00:09:50 +090044int System::Ioctl(int fd, ioctl_req_t request, const char* argp) {
45 return ioctl(fd, request, argp);
46}
47
48int System::Ioctl(int fd, ioctl_req_t request, uint64_t arg) {
49 return Ioctl(fd, request, reinterpret_cast<const char*>(arg));
50}
51
52int System::Ioctl(int fd, ioctl_req_t request, struct ifreq* ifr) {
53 return Ioctl(fd, request, reinterpret_cast<const char*>(ifr));
54}
55
56int System::Ioctl(int fd, ioctl_req_t request, struct rtentry* route) {
57 return Ioctl(fd, request, reinterpret_cast<const char*>(route));
58}
59
Hugo Benichi96ee6f62021-06-28 14:07:20 +090060pid_t System::WaitPid(pid_t pid, int* wstatus, int options) {
61 return waitpid(pid, wstatus, options);
62}
63
Hugo Benichi153c7112021-02-22 17:46:33 +090064bool System::SysNetSet(SysNet target,
65 const std::string& content,
66 const std::string& iface) {
67 std::string path;
68 switch (target) {
69 case SysNet::IPv4Forward:
70 return Write(kSysNetIPv4ForwardingPath, content);
71 case SysNet::IPLocalPortRange:
72 return Write(kSysNetIPLocalPortRangePath, content);
73 case SysNet::IPv4RouteLocalnet:
74 if (iface.empty()) {
75 LOG(ERROR) << "IPv4LocalPortRange requires a valid interface";
76 return false;
77 }
78 return Write(
79 kSysNetIPv4ConfPrefix + iface + kSysNetIPv4RouteLocalnetSuffix,
80 content);
81 case SysNet::IPv6Forward:
82 return Write(kSysNetIPv6ForwardingPath, content);
83 case SysNet::IPv6AcceptRA:
84 if (iface.empty()) {
85 LOG(ERROR) << "IPv6AcceptRA requires a valid interface";
86 return false;
87 }
88 return Write(kSysNetIPv6ConfPrefix + iface + kSysNetIPv6AcceptRaSuffix,
89 content);
90 case ConntrackHelper:
91 return Write(kSysNetConntrackHelperPath, content);
92 default:
93 LOG(ERROR) << "Unknown SysNet value " << target;
94 return false;
95 }
96}
97
98bool System::Write(const std::string& path, const std::string& content) {
99 base::ScopedFD fd(open(path.c_str(), O_WRONLY | O_TRUNC | O_CLOEXEC));
100 if (!fd.is_valid()) {
101 PLOG(ERROR) << "Failed to open " << path;
102 return false;
103 }
104
105 if (write(fd.get(), content.c_str(), content.size()) != content.size()) {
106 PLOG(ERROR) << "Failed to write \"" << content << "\" to " << path;
107 return false;
108 }
109
110 return true;
111}
112
Hugo Benichif818c782021-04-10 00:09:50 +0900113} // namespace patchpanel