Automated g4 rollback of changelist 588486234.
*** Reason for rollback ***
Roll forward with fix.
Fairly simple fix. Had accidentally left out some returns after QUICHE_NOTREACHED(). Causes an issue only when building opt (apparently not done in my initial SQ) when the NOTREACHED noops out of existence.
Confirmed a `--compilation_mode=opt third_party/quic/core/io:all` build/test succeeds with this fix and fails without.
*** Original change description ***
Automated g4 rollback of changelist 588217549.
*** Reason for rollback ***
Broke builds.
*** Original change description ***
Allow creation of Raw IP sockets in QUICHE
***
***
PiperOrigin-RevId: 588769610
diff --git a/quiche/quic/core/io/event_loop_connecting_client_socket_test.cc b/quiche/quic/core/io/event_loop_connecting_client_socket_test.cc
index c7e18ce..f195d9d 100644
--- a/quiche/quic/core/io/event_loop_connecting_client_socket_test.cc
+++ b/quiche/quic/core/io/event_loop_connecting_client_socket_test.cc
@@ -4,16 +4,16 @@
#include "quiche/quic/core/io/event_loop_connecting_client_socket.h"
-#include <functional>
#include <memory>
#include <optional>
#include <string>
+#include <tuple>
#include <utility>
-#include <vector>
#include "absl/functional/bind_front.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "quiche/quic/core/connecting_client_socket.h"
@@ -22,7 +22,7 @@
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/io/socket.h"
#include "quiche/quic/core/quic_time.h"
-#include "quiche/quic/platform/api/quic_ip_address_family.h"
+#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/quic/test_tools/mock_clock.h"
#include "quiche/quic/test_tools/quic_test_utils.h"
@@ -200,6 +200,10 @@
return socket_factory_->CreateTcpClientSocket(
peer_address, /*receive_buffer_size=*/0, /*send_buffer_size=*/0,
async_visitor);
+ default:
+ // Unexpected protocol.
+ QUICHE_NOTREACHED();
+ return nullptr;
}
}
@@ -219,6 +223,10 @@
return socket_factory_->CreateTcpClientSocket(
peer_address, /*receive_buffer_size=*/0, /*send_buffer_size=*/4,
async_visitor);
+ default:
+ // Unexpected protocol.
+ QUICHE_NOTREACHED();
+ return nullptr;
}
}
@@ -275,6 +283,9 @@
runner = std::make_unique<TestTcpServerSocketRunner>(
server_socket_descriptor_, std::move(behavior));
break;
+ default:
+ // Unexpected protocol.
+ QUICHE_NOTREACHED();
}
// Runner takes responsibility for closing server socket.
@@ -375,6 +386,9 @@
EXPECT_TRUE(connect_result_.value().ok());
socket->Disconnect();
break;
+ default:
+ // Unexpected protocol.
+ FAIL();
}
}
@@ -411,6 +425,9 @@
// server.
EXPECT_TRUE(connect_result_.value().ok());
break;
+ default:
+ // Unexpected protocol.
+ FAIL();
}
}
@@ -659,6 +676,9 @@
socket->SendAsync(data);
expected = data;
break;
+ default:
+ // Unexpected protocol.
+ FAIL();
}
ASSERT_TRUE(send_result_.has_value());
EXPECT_TRUE(send_result_.value().ok());
diff --git a/quiche/quic/core/io/socket.cc b/quiche/quic/core/io/socket.cc
index 0118003..d41106f 100644
--- a/quiche/quic/core/io/socket.cc
+++ b/quiche/quic/core/io/socket.cc
@@ -50,10 +50,10 @@
}
}
-absl::Status SetSockOptInt(SocketFd fd, int option, int value) {
+absl::Status SetSockOptInt(SocketFd fd, int level, int option, int value) {
QUICHE_DCHECK_NE(fd, kInvalidSocketFd);
- int result = SyscallSetsockopt(fd, SOL_SOCKET, option, &value, sizeof(value));
+ int result = SyscallSetsockopt(fd, level, option, &value, sizeof(value));
if (result >= 0) {
return absl::OkStatus();
@@ -71,14 +71,21 @@
QUICHE_DCHECK_NE(fd, kInvalidSocketFd);
QUICHE_DCHECK_LE(size, QuicByteCount{INT_MAX});
- return SetSockOptInt(fd, SO_RCVBUF, static_cast<int>(size));
+ return SetSockOptInt(fd, SOL_SOCKET, SO_RCVBUF, static_cast<int>(size));
}
absl::Status SetSendBufferSize(SocketFd fd, QuicByteCount size) {
QUICHE_DCHECK_NE(fd, kInvalidSocketFd);
QUICHE_DCHECK_LE(size, QuicByteCount{INT_MAX});
- return SetSockOptInt(fd, SO_SNDBUF, static_cast<int>(size));
+ return SetSockOptInt(fd, SOL_SOCKET, SO_SNDBUF, static_cast<int>(size));
+}
+
+absl::Status SetIpHeaderIncluded(SocketFd fd, bool ip_header_included) {
+ QUICHE_DCHECK_NE(fd, kInvalidSocketFd);
+
+ return SetSockOptInt(fd, IPPROTO_IP, IP_HDRINCL,
+ static_cast<int>(ip_header_included));
}
absl::Status Connect(SocketFd fd, const QuicSocketAddress& peer_address) {
diff --git a/quiche/quic/core/io/socket.h b/quiche/quic/core/io/socket.h
index edff4ee..319dff4 100644
--- a/quiche/quic/core/io/socket.h
+++ b/quiche/quic/core/io/socket.h
@@ -5,9 +5,6 @@
#ifndef QUICHE_QUIC_CORE_IO_SOCKET_H_
#define QUICHE_QUIC_CORE_IO_SOCKET_H_
-#include <functional>
-#include <string>
-
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
@@ -15,7 +12,6 @@
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/platform/api/quic_ip_address_family.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
-#include "quiche/common/platform/api/quiche_export.h"
#if defined(_WIN32)
#include <winsock2.h>
@@ -42,6 +38,7 @@
enum class SocketProtocol {
kUdp,
kTcp,
+ kRawIp,
};
inline absl::string_view GetProtocolName(SocketProtocol protocol) {
@@ -50,6 +47,8 @@
return "UDP";
case SocketProtocol::kTcp:
return "TCP";
+ case SocketProtocol::kRawIp:
+ return "RAW_IP";
}
return "unknown";
@@ -76,6 +75,11 @@
absl::Status SetReceiveBufferSize(SocketFd fd, QuicByteCount size);
absl::Status SetSendBufferSize(SocketFd fd, QuicByteCount size);
+// Only allowed for raw IP sockets. If set, sent data buffers include the IP
+// header. If not set, sent data buffers only contain the IP packet payload, and
+// the header will be generated.
+absl::Status SetIpHeaderIncluded(SocketFd fd, bool ip_header_included);
+
// Connects socket `fd` to `peer_address`. Returns a status with
// `absl::StatusCode::kUnavailable` iff the socket is non-blocking and the
// connection could not be immediately completed. The socket will then complete
diff --git a/quiche/quic/core/io/socket_internal.h b/quiche/quic/core/io/socket_internal.h
index 3fc9f00..d11c0ef 100644
--- a/quiche/quic/core/io/socket_internal.h
+++ b/quiche/quic/core/io/socket_internal.h
@@ -21,6 +21,8 @@
return SOCK_DGRAM;
case SocketProtocol::kTcp:
return SOCK_STREAM;
+ case SocketProtocol::kRawIp:
+ return SOCK_RAW;
}
QUICHE_NOTREACHED();
@@ -33,6 +35,8 @@
return IPPROTO_UDP;
case SocketProtocol::kTcp:
return IPPROTO_TCP;
+ case SocketProtocol::kRawIp:
+ return IPPROTO_RAW;
}
QUICHE_NOTREACHED();
diff --git a/quiche/quic/core/io/socket_test.cc b/quiche/quic/core/io/socket_test.cc
index da1d24a..9e18cc1 100644
--- a/quiche/quic/core/io/socket_test.cc
+++ b/quiche/quic/core/io/socket_test.cc
@@ -5,13 +5,12 @@
#include "quiche/quic/core/io/socket.h"
#include <string>
-#include <utility>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
-#include "quiche/quic/platform/api/quic_ip_address_family.h"
+#include "quiche/quic/platform/api/quic_ip_address.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/platform/api/quiche_test.h"
@@ -39,6 +38,20 @@
}
}
+SocketFd CreateTestRawSocket(bool blocking = true) {
+ absl::StatusOr<SocketFd> socket =
+ socket_api::CreateSocket(quiche::TestLoopback().address_family(),
+ socket_api::SocketProtocol::kRawIp, blocking);
+
+ if (socket.ok()) {
+ return socket.value();
+ } else {
+ // This is expected if test not run with relevant admin privileges.
+ QUICHE_CHECK(absl::IsPermissionDenied(socket.status()));
+ return kInvalidSocketFd;
+ }
+}
+
TEST(SocketTest, CreateAndCloseSocket) {
QuicIpAddress localhost_address = quiche::TestLoopback();
absl::StatusOr<SocketFd> created_socket = socket_api::CreateSocket(
@@ -49,6 +62,22 @@
QUICHE_EXPECT_OK(socket_api::Close(created_socket.value()));
}
+TEST(SocketTest, CreateAndCloseRawSocket) {
+ QuicIpAddress localhost_address = quiche::TestLoopback();
+ absl::StatusOr<SocketFd> created_socket = socket_api::CreateSocket(
+ localhost_address.address_family(), socket_api::SocketProtocol::kRawIp);
+
+ // Raw IP socket creation will typically fail if not run with relevant admin
+ // privileges.
+ if (!created_socket.ok()) {
+ EXPECT_THAT(created_socket.status(),
+ StatusIs(absl::StatusCode::kPermissionDenied));
+ return;
+ }
+
+ QUICHE_EXPECT_OK(socket_api::Close(created_socket.value()));
+}
+
TEST(SocketTest, SetSocketBlocking) {
SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
/*blocking=*/true);
@@ -76,6 +105,30 @@
QUICHE_EXPECT_OK(socket_api::Close(socket));
}
+TEST(SocketTest, SetIpHeaderIncludedForRaw) {
+ SocketFd socket = CreateTestRawSocket(/*blocking=*/true);
+ if (socket == kInvalidSocketFd) {
+ return;
+ }
+
+ QUICHE_EXPECT_OK(
+ socket_api::SetIpHeaderIncluded(socket, /*ip_header_included=*/true));
+
+ QUICHE_EXPECT_OK(socket_api::Close(socket));
+}
+
+TEST(SocketTest, SetIpHeaderIncludedForUdp) {
+ SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
+ /*blocking=*/true);
+
+ // Expect option only allowed for raw IP sockets.
+ EXPECT_THAT(
+ socket_api::SetIpHeaderIncluded(socket, /*ip_header_included=*/true),
+ StatusIs(absl::StatusCode::kInvalidArgument));
+
+ QUICHE_EXPECT_OK(socket_api::Close(socket));
+}
+
TEST(SocketTest, Connect) {
SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp);