| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/base/sockaddr_util_posix.h" |
| |
| #include <string.h> |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| |
| #include "base/containers/span.h" |
| #include "base/strings/string_view_util.h" |
| #include "net/base/sockaddr_storage.h" |
| #include "testing/gmock/include/gmock/gmock-matchers.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| // The largest possible platform-dependent value. Subtracting one for an extra |
| // NUL character at the front or back. |
| constexpr size_t kMaxUnixAddressPath = sizeof(sockaddr_un::sun_path) - 1; |
| |
| } // namespace |
| |
| TEST(FillUnixAddressTest, SimpleAddress) { |
| SockaddrStorage storage; |
| std::string path = "/tmp/socket/path"; |
| |
| EXPECT_TRUE( |
| FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); |
| |
| // |storage.addr_len| indicates the full size of the data in sockaddr_un. |
| // The size is increased by one byte to include the string NUL terminator. |
| EXPECT_EQ(path.size() + 1U + offsetof(struct sockaddr_un, sun_path), |
| (unsigned int)storage.addr_len); |
| |
| struct sockaddr_un* socket_addr = |
| reinterpret_cast<struct sockaddr_un*>(&storage.addr_storage); |
| EXPECT_EQ(socket_addr->sun_family, AF_UNIX); |
| |
| // Implicit conversion to std::string for comparison is fine since the path |
| // is always NUL terminated. |
| EXPECT_EQ(socket_addr->sun_path, path); |
| } |
| |
| TEST(FillUnixAddressTest, PathEmpty) { |
| SockaddrStorage storage; |
| std::string path = ""; |
| EXPECT_FALSE( |
| FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); |
| } |
| |
| TEST(FillUnixAddressTest, AddressMaxLength) { |
| SockaddrStorage storage; |
| std::string path(kMaxUnixAddressPath, '0'); |
| |
| EXPECT_TRUE( |
| FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); |
| |
| struct sockaddr_un* socket_addr = |
| reinterpret_cast<struct sockaddr_un*>(&storage.addr_storage); |
| EXPECT_EQ(socket_addr->sun_family, AF_UNIX); |
| EXPECT_EQ(socket_addr->sun_path, path); |
| } |
| |
| TEST(FillUnixAddressTest, AddressTooLong) { |
| SockaddrStorage storage; |
| std::string path(kMaxUnixAddressPath + 1, '0'); |
| |
| EXPECT_FALSE( |
| FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); |
| } |
| |
| TEST(FillUnixAddressTest, AbstractLinuxAddress) { |
| SockaddrStorage storage; |
| std::string path(kMaxUnixAddressPath, '0'); |
| |
| #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
| EXPECT_TRUE(FillUnixAddress(path, /*use_abstract_namespace=*/true, &storage)); |
| |
| EXPECT_EQ(path.size() + 1U + offsetof(struct sockaddr_un, sun_path), |
| static_cast<size_t>(storage.addr_len)); |
| |
| struct sockaddr_un* socket_addr = |
| reinterpret_cast<struct sockaddr_un*>(&storage.addr_storage); |
| EXPECT_EQ(socket_addr->sun_family, AF_UNIX); |
| |
| // The path buffer is preceded by a NUL character for abstract Linux |
| // addresses. |
| EXPECT_EQ(socket_addr->sun_path[0], '\0'); |
| |
| // The rest of the path. Note that `addr_len` has already been verified to be |
| // correct, so only need to check the remaining path.size() characters of the |
| // address struct, after the nul. Create a span and then a string_view from it |
| // because span's constructor creates a span from the length of the array |
| // that's passed in, while string_view's constructor will treat the input as |
| // C-string and look for the terminating null at the end, and abstract Linux |
| // paths are not guaranteed to be null terminated when in a `sockaddr_un`. |
| std::string_view unix_path = base::as_string_view( |
| base::span(socket_addr->sun_path).subspan(1u, path.size())); |
| EXPECT_EQ(unix_path, path); |
| #else |
| // Other platforms don't support the abstract Linux namespace. |
| EXPECT_FALSE( |
| FillUnixAddress(path, /*use_abstract_namespace=*/true, &storage)); |
| #endif |
| } |
| |
| } // namespace net |