Merge pull request #6085 from liornm:fix-tun-no_pi

PiperOrigin-RevId: 382202462
This commit is contained in:
gVisor bot
2021-06-29 17:54:17 -07:00
2 changed files with 53 additions and 7 deletions
+9 -7
View File
@@ -208,6 +208,15 @@ func (d *Device) Write(data []byte) (int64, error) {
protocol = pktInfoHdr.Protocol()
case ethHdr != nil:
protocol = ethHdr.Type()
case d.flags.TUN:
// TUN interface with IFF_NO_PI enabled, thus
// we need to determine protocol from version field
version := data[0] >> 4
if version == 4 {
protocol = header.IPv4ProtocolNumber
} else if version == 6 {
protocol = header.IPv6ProtocolNumber
}
}
// Try to determine remote link address, default zero.
@@ -265,13 +274,6 @@ func (d *Device) encodePkt(info *channel.PacketInfo) (buffer.View, bool) {
vv.AppendView(buffer.View(hdr))
}
// If the packet does not already have link layer header, and the route
// does not exist, we can't compute it. This is possibly a raw packet, tun
// device doesn't support this at the moment.
if info.Pkt.LinkHeader().View().IsEmpty() && len(info.Route.RemoteLinkAddress) == 0 {
return nil, false
}
// Ethernet header (TAP only).
if d.flags.TAP {
// Add ethernet header if not provided.
+44
View File
@@ -24,6 +24,8 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <cstddef>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/ascii.h"
@@ -44,6 +46,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 +416,47 @@ 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) {