mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Merge pull request #6085 from liornm:fix-tun-no_pi
PiperOrigin-RevId: 382202462
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user