summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux
diff options
context:
space:
mode:
authorliornm <lior.neumann@gmail.com>2021-05-27 17:03:44 +0300
committerliornm <lior.neumann@gmail.com>2021-06-29 10:51:58 +0300
commitddbc27365978a7c634354000094f86022d3ecd2f (patch)
treeace08aacbdd1517b1bcec1c760a4fddeaca38edc /test/syscalls/linux
parent32b66bb2be1b3b56138ca856045381519e210b68 (diff)
Fix TUN IFF_NO_PI bug
When TUN is created with IFF_NO_PI flag, there will be no Ethernet header and no packet info, therefore, both read and write will fail. This commit fix this bug.
Diffstat (limited to 'test/syscalls/linux')
-rw-r--r--test/syscalls/linux/tuntap.cc39
1 files changed, 39 insertions, 0 deletions
diff --git a/test/syscalls/linux/tuntap.cc b/test/syscalls/linux/tuntap.cc
index 279fe342c..e209b9cbc 100644
--- a/test/syscalls/linux/tuntap.cc
+++ b/test/syscalls/linux/tuntap.cc
@@ -23,6 +23,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
+#include <cstddef>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -44,6 +45,7 @@ constexpr int kIPLen = 4;
constexpr const char kDevNetTun[] = "/dev/net/tun";
constexpr const char kTapName[] = "tap0";
+constexpr const char kTunName[] = "tun0";
#define kTapIPAddr htonl(0x0a000001) /* Inet 10.0.0.1 */
#define kTapPeerIPAddr htonl(0x0a000002) /* Inet 10.0.0.2 */
@@ -413,6 +415,43 @@ TEST_F(TuntapTest, SendUdpTriggersArpResolution) {
}
}
+TEST_F(TuntapTest, TUNNoPacketInfo) {
+ SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));
+
+ // Interface creation.
+ FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(kDevNetTun, O_RDWR));
+
+ struct ifreq ifr_set = {};
+ ifr_set.ifr_flags = IFF_TUN | IFF_NO_PI;
+ strncpy(ifr_set.ifr_name, kTunName, IFNAMSIZ);
+ EXPECT_THAT(ioctl(fd.get(), TUNSETIFF, &ifr_set), SyscallSucceeds());
+
+ // Interface setup.
+ auto link = ASSERT_NO_ERRNO_AND_VALUE(GetLinkByName(kTunName));
+ const struct in_addr dev_ipv4_addr = {.s_addr = kTapIPAddr};
+ EXPECT_NO_ERRNO(LinkAddLocalAddr(link.index, AF_INET, 24, &dev_ipv4_addr, sizeof(dev_ipv4_addr)));
+
+ ping_pkt ping_req = CreatePingPacket(kMacB, kTapPeerIPAddr, kMacA, kTapIPAddr);
+ size_t packet_size = sizeof(ping_req) - offsetof(ping_pkt, ip);
+
+ // Send ICMP query
+ EXPECT_THAT(write(fd.get(), &ping_req.ip, packet_size), SyscallSucceedsWithValue(packet_size));
+
+ // Receive loop to process inbound packets.
+ while (1) {
+ ping_pkt ping_resp = {};
+ EXPECT_THAT(read(fd.get(), &ping_resp.ip, packet_size), SyscallSucceedsWithValue(packet_size));
+
+ // Process ping response packet.
+ if (!memcmp(&ping_resp.ip.saddr, &ping_req.ip.daddr, kIPLen) &&
+ !memcmp(&ping_resp.ip.daddr, &ping_req.ip.saddr, kIPLen) &&
+ ping_resp.icmp.type == 0 && ping_resp.icmp.code == 0) {
+ // Ends and passes the test.
+ break;
+ }
+ }
+}
+
// TCPBlockingConnectFailsArpResolution tests for TCP connect to fail on link
// address resolution failure to a routable, but non existent peer.
TEST_F(TuntapTest, TCPBlockingConnectFailsArpResolution) {