| // Copyright 2022 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef PATCHPANEL_FAKE_SYSTEM_H_ |
| #define PATCHPANEL_FAKE_SYSTEM_H_ |
| |
| #include <fcntl.h> |
| #include <linux/if_tun.h> |
| #include <linux/sockios.h> |
| |
| #include <string> |
| #include <string_view> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/files/file_path.h> |
| #include <base/files/scoped_file.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "patchpanel/system.h" |
| |
| namespace patchpanel { |
| class FakeSystem : public System { |
| public: |
| FakeSystem() = default; |
| ~FakeSystem() override = default; |
| |
| // Capture Ioctls operations and arguments. Always succeeds. |
| int Ioctl(int fd, ioctl_req_t request, const char* argp) override { |
| ioctl_reqs.push_back(request); |
| switch (request) { |
| case SIOCBRADDBR: |
| case SIOCBRDELBR: { |
| ioctl_ifreq_args.push_back({std::string(argp), {}}); |
| break; |
| } |
| } |
| return 0; |
| } |
| |
| int Ioctl(int fd, ioctl_req_t request, uint64_t arg) override { |
| ioctl_reqs.push_back(request); |
| return 0; |
| } |
| |
| int Ioctl(int fd, ioctl_req_t request, struct ifreq* ifr) override { |
| ioctl_reqs.push_back(request); |
| switch (request) { |
| case SIOCBRADDIF: |
| case TUNSETIFF: |
| case SIOCSIFADDR: |
| case SIOCSIFNETMASK: |
| case SIOCSIFHWADDR: |
| case SIOCGIFFLAGS: |
| case SIOCSIFFLAGS: { |
| ioctl_ifreq_args.push_back({std::string(ifr->ifr_name), *ifr}); |
| break; |
| } |
| } |
| return 0; |
| } |
| |
| int Ioctl(int fd, ioctl_req_t request, struct rtentry* route) override { |
| ioctl_reqs.push_back(request); |
| switch (request) { |
| case SIOCADDRT: |
| case SIOCDELRT: { |
| ioctl_rtentry_args.push_back({"", *route}); |
| // Copy the string pointed by rtentry.rt_dev because Add/DeleteIPv4Route |
| // pass this value to ioctl() on the stack. |
| if (route->rt_dev) { |
| auto& cap = ioctl_rtentry_args.back(); |
| cap.first = std::string(route->rt_dev); |
| cap.second.rt_dev = const_cast<char*>(cap.first.c_str()); |
| } |
| break; |
| } |
| } |
| return 0; |
| } |
| |
| int Ioctl(int fd, ioctl_req_t request, struct in6_rtmsg* route) override { |
| ioctl_reqs.push_back(request); |
| return 0; |
| } |
| |
| base::ScopedFD OpenTunDev() override { |
| return base::ScopedFD(open("/dev/null", O_RDONLY | O_CLOEXEC)); |
| } |
| |
| MOCK_METHOD(int, SocketPair, (int, int, int, int[2]), (override)); |
| MOCK_METHOD(bool, |
| SysNetSet, |
| (SysNet, std::string_view, std::string_view), |
| (override)); |
| MOCK_METHOD(std::string, |
| SysNetGet, |
| (SysNet, std::string_view), |
| (const, override)); |
| MOCK_METHOD(int, IfNametoindex, (std::string_view), (override)); |
| MOCK_METHOD(std::string, IfIndextoname, (int), (override)); |
| MOCK_METHOD(bool, |
| WriteConfigFile, |
| (base::FilePath, std::string_view), |
| (override)); |
| |
| bool IsEbpfEnabled() const override { return true; } |
| |
| std::vector<ioctl_req_t> ioctl_reqs; |
| std::vector<std::pair<std::string, struct rtentry>> ioctl_rtentry_args; |
| std::vector<std::pair<std::string, struct ifreq>> ioctl_ifreq_args; |
| }; |
| |
| } // namespace patchpanel |
| |
| #endif // PATCHPANEL_FAKE_SYSTEM_H_ |