blob: fb4b773ea4dfcddad353a5ef8be21ecdb54a148d [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>
Hugo Benichi03be8962022-03-17 13:16:38 +09008#include <net/if.h>
Hugo Benichi153c7112021-02-22 17:46:33 +09009#include <sys/stat.h>
Hugo Benichi96ee6f62021-06-28 14:07:20 +090010#include <sys/wait.h>
Hugo Benichi153c7112021-02-22 17:46:33 +090011#include <unistd.h>
12
13#include <base/files/scoped_file.h>
Qijiang Fan80174b72021-08-13 12:48:38 +090014#include <base/logging.h>
Hugo Benichi153c7112021-02-22 17:46:33 +090015
Hugo Benichif818c782021-04-10 00:09:50 +090016namespace patchpanel {
17
Hugo Benichi153c7112021-02-22 17:46:33 +090018namespace {
19
20// /proc/sys/ paths and fragments used for System::SysNetSet
21// Defines the local port range that is used by TCP and UDP traffic to choose
22// the local port (IPv4 and IPv6).
23constexpr const char kSysNetIPLocalPortRangePath[] =
24 "/proc/sys/net/ipv4/ip_local_port_range";
25// Enables/Disables IPv4 forwarding between interfaces.
26constexpr const char kSysNetIPv4ForwardingPath[] =
27 "/proc/sys/net/ipv4/ip_forward";
28// /proc/sys path for controlling connection tracking helper modules
29constexpr const char kSysNetConntrackHelperPath[] =
30 "/proc/sys/net/netfilter/nf_conntrack_helper";
Jason Jeremy Imana183d7a2021-08-06 01:35:40 +090031// Enables/Disables IPv6.
32constexpr const char kSysNetDisableIPv6Path[] =
33 "/proc/sys/net/ipv6/conf/all/disable_ipv6";
Hugo Benichi153c7112021-02-22 17:46:33 +090034// Prefix for IPv4 interface configuration.
35constexpr const char kSysNetIPv4ConfPrefix[] = "/proc/sys/net/ipv4/conf/";
36// Suffix for allowing localhost as a source or destination when routing IPv4.
37constexpr const char kSysNetIPv4RouteLocalnetSuffix[] = "/route_localnet";
38// Enables/Disables IPv6 forwarding between interfaces.
39constexpr const char kSysNetIPv6ForwardingPath[] =
40 "/proc/sys/net/ipv6/conf/all/forwarding";
41// Prefix for IPv6 interface configuration.
42constexpr const char kSysNetIPv6ConfPrefix[] = "/proc/sys/net/ipv6/conf/";
43// Suffix for accepting Router Advertisements on an interface and
44// autoconfiguring it with IPv6 parameters.
45constexpr const char kSysNetIPv6AcceptRaSuffix[] = "/accept_ra";
46
47} // namespace
48
Hugo Benichif818c782021-04-10 00:09:50 +090049int System::Ioctl(int fd, ioctl_req_t request, const char* argp) {
50 return ioctl(fd, request, argp);
51}
52
53int System::Ioctl(int fd, ioctl_req_t request, uint64_t arg) {
54 return Ioctl(fd, request, reinterpret_cast<const char*>(arg));
55}
56
57int System::Ioctl(int fd, ioctl_req_t request, struct ifreq* ifr) {
58 return Ioctl(fd, request, reinterpret_cast<const char*>(ifr));
59}
60
61int System::Ioctl(int fd, ioctl_req_t request, struct rtentry* route) {
62 return Ioctl(fd, request, reinterpret_cast<const char*>(route));
63}
64
Hugo Benichi96ee6f62021-06-28 14:07:20 +090065pid_t System::WaitPid(pid_t pid, int* wstatus, int options) {
66 return waitpid(pid, wstatus, options);
67}
68
Hugo Benichi153c7112021-02-22 17:46:33 +090069bool System::SysNetSet(SysNet target,
70 const std::string& content,
71 const std::string& iface) {
72 std::string path;
73 switch (target) {
74 case SysNet::IPv4Forward:
75 return Write(kSysNetIPv4ForwardingPath, content);
76 case SysNet::IPLocalPortRange:
77 return Write(kSysNetIPLocalPortRangePath, content);
78 case SysNet::IPv4RouteLocalnet:
79 if (iface.empty()) {
80 LOG(ERROR) << "IPv4LocalPortRange requires a valid interface";
81 return false;
82 }
83 return Write(
84 kSysNetIPv4ConfPrefix + iface + kSysNetIPv4RouteLocalnetSuffix,
85 content);
86 case SysNet::IPv6Forward:
87 return Write(kSysNetIPv6ForwardingPath, content);
88 case SysNet::IPv6AcceptRA:
89 if (iface.empty()) {
90 LOG(ERROR) << "IPv6AcceptRA requires a valid interface";
91 return false;
92 }
93 return Write(kSysNetIPv6ConfPrefix + iface + kSysNetIPv6AcceptRaSuffix,
94 content);
95 case ConntrackHelper:
96 return Write(kSysNetConntrackHelperPath, content);
Jason Jeremy Imana183d7a2021-08-06 01:35:40 +090097 case SysNet::IPv6Disable:
98 return Write(kSysNetDisableIPv6Path, content);
Hugo Benichi153c7112021-02-22 17:46:33 +090099 default:
100 LOG(ERROR) << "Unknown SysNet value " << target;
101 return false;
102 }
103}
104
Hugo Benichi03be8962022-03-17 13:16:38 +0900105std::string System::IfIndextoname(int ifindex) {
106 char ifname[IFNAMSIZ];
107 if (if_indextoname(ifindex, ifname) == nullptr) {
108 return "";
109 }
110 return ifname;
111}
112
113uint32_t System::IfNametoindex(const std::string& ifname) {
114 uint32_t ifindex = if_nametoindex(ifname.c_str());
115 if (ifindex > 0) {
116 if_nametoindex_[ifname] = ifindex;
117 return ifindex;
118 }
119
120 const auto it = if_nametoindex_.find(ifname);
121 if (it != if_nametoindex_.end())
122 return it->second;
123
124 return 0;
125}
126
127// static
Hugo Benichi153c7112021-02-22 17:46:33 +0900128bool System::Write(const std::string& path, const std::string& content) {
129 base::ScopedFD fd(open(path.c_str(), O_WRONLY | O_TRUNC | O_CLOEXEC));
130 if (!fd.is_valid()) {
131 PLOG(ERROR) << "Failed to open " << path;
132 return false;
133 }
134
135 if (write(fd.get(), content.c_str(), content.size()) != content.size()) {
136 PLOG(ERROR) << "Failed to write \"" << content << "\" to " << path;
137 return false;
138 }
139
140 return true;
141}
142
Hugo Benichif818c782021-04-10 00:09:50 +0900143} // namespace patchpanel