diff options
author | Tony Gong <gongt@google.com> | 2020-07-07 16:13:21 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-07-07 16:14:49 -0700 |
commit | 76c7bc51b7b02c4ba83c0a064c3629bb5ee91340 (patch) | |
tree | 48c1525ebbb54fc47a3cbd46c4e3efee957300aa /test/syscalls | |
parent | 7e4d2d63eef3f643222181b3a227bfc7ebe44db2 (diff) |
Set IPv4 ID on all non-atomic datagrams
RFC 6864 imposes various restrictions on the uniqueness of the IPv4
Identification field for non-atomic datagrams, defined as an IP datagram that
either can be fragmented (DF=0) or is already a fragment (MF=1 or positive
fragment offset). In order to be compliant, the ID field is assigned for all
non-atomic datagrams.
Add a TCP unit test that induces retransmissions and checks that the IPv4
ID field is unique every time. Add basic handling of the IP_MTU_DISCOVER
socket option so that the option can be used to disable PMTU discovery,
effectively setting DF=0. Attempting to set the sockopt to anything other
than disabled will fail because PMTU discovery is currently not implemented,
and the default behavior matches that of disabled.
PiperOrigin-RevId: 320081842
Diffstat (limited to 'test/syscalls')
-rw-r--r-- | test/syscalls/linux/raw_socket_hdrincl.cc | 51 |
1 files changed, 3 insertions, 48 deletions
diff --git a/test/syscalls/linux/raw_socket_hdrincl.cc b/test/syscalls/linux/raw_socket_hdrincl.cc index 0a27506aa..16cfc1d75 100644 --- a/test/syscalls/linux/raw_socket_hdrincl.cc +++ b/test/syscalls/linux/raw_socket_hdrincl.cc @@ -273,52 +273,7 @@ TEST_F(RawHDRINCL, SendAndReceive) { // The network stack should have set the source address. EXPECT_EQ(src.sin_family, AF_INET); EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK); - // The packet ID should be 0, as the packet is less than 68 bytes. - struct iphdr iphdr = {}; - memcpy(&iphdr, recv_buf, sizeof(iphdr)); - EXPECT_EQ(iphdr.id, 0); -} - -// Send and receive a packet with nonzero IP ID. -TEST_F(RawHDRINCL, SendAndReceiveNonzeroID) { - int port = 40000; - if (!IsRunningOnGvisor()) { - port = static_cast<short>(ASSERT_NO_ERRNO_AND_VALUE( - PortAvailable(0, AddressFamily::kIpv4, SocketType::kUdp, false))); - } - - // IPPROTO_RAW sockets are write-only. We'll have to open another socket to - // read what we write. - FileDescriptor udp_sock = - ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP)); - - // Construct a packet with an IP header, UDP header, and payload. Make the - // payload large enough to force an IP ID to be assigned. - constexpr char kPayload[128] = {}; - char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)]; - ASSERT_TRUE( - FillPacket(packet, sizeof(packet), port, kPayload, sizeof(kPayload))); - - socklen_t addrlen = sizeof(addr_); - ASSERT_NO_FATAL_FAILURE(sendto(socket_, &packet, sizeof(packet), 0, - reinterpret_cast<struct sockaddr*>(&addr_), - addrlen)); - - // Receive the payload. - char recv_buf[sizeof(packet)]; - struct sockaddr_in src; - socklen_t src_size = sizeof(src); - ASSERT_THAT(recvfrom(udp_sock.get(), recv_buf, sizeof(recv_buf), 0, - reinterpret_cast<struct sockaddr*>(&src), &src_size), - SyscallSucceedsWithValue(sizeof(packet))); - EXPECT_EQ( - memcmp(kPayload, recv_buf + sizeof(struct iphdr) + sizeof(struct udphdr), - sizeof(kPayload)), - 0); - // The network stack should have set the source address. - EXPECT_EQ(src.sin_family, AF_INET); - EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK); - // The packet ID should not be 0, as the packet was more than 68 bytes. + // The packet ID should not be 0, as the packet has DF=0. struct iphdr* iphdr = reinterpret_cast<struct iphdr*>(recv_buf); EXPECT_NE(iphdr->id, 0); } @@ -368,10 +323,10 @@ TEST_F(RawHDRINCL, SendAndReceiveDifferentAddress) { // The network stack should have set the source address. EXPECT_EQ(src.sin_family, AF_INET); EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK); - // The packet ID should be 0, as the packet is less than 68 bytes. + // The packet ID should not be 0, as the packet has DF=0. struct iphdr recv_iphdr = {}; memcpy(&recv_iphdr, recv_buf, sizeof(recv_iphdr)); - EXPECT_EQ(recv_iphdr.id, 0); + EXPECT_NE(recv_iphdr.id, 0); // The destination address should be localhost, not the bad IP we set // initially. EXPECT_EQ(absl::gbswap_32(recv_iphdr.daddr), INADDR_LOOPBACK); |