mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Support add/remove IPv6 multicast group sock opt
IPv4 was always supported but UDP never supported joining/leaving IPv6 multicast groups via socket options. Add: IPPROTO_IPV6, IPV6_JOIN_GROUP/IPV6_ADD_MEMBERSHIP Remove: IPPROTO_IPV6, IPV6_LEAVE_GROUP/IPV6_DROP_MEMBERSHIP Test: integration_test.TestUDPAddRemoveMembershipSocketOption PiperOrigin-RevId: 350396072
This commit is contained in:
committed by
gVisor bot
parent
0c4118d5b8
commit
abe9d9f67f
@@ -250,6 +250,12 @@ type SockAddrInet struct {
|
||||
_ [8]uint8 // pad to sizeof(struct sockaddr).
|
||||
}
|
||||
|
||||
// Inet6MulticastRequest is struct ipv6_mreq, from uapi/linux/in6.h.
|
||||
type Inet6MulticastRequest struct {
|
||||
MulticastAddr Inet6Addr
|
||||
InterfaceIndex int32
|
||||
}
|
||||
|
||||
// InetMulticastRequest is struct ip_mreq, from uapi/linux/in.h.
|
||||
type InetMulticastRequest struct {
|
||||
MulticastAddr InetAddr
|
||||
|
||||
@@ -2091,9 +2091,29 @@ func setSockOptIPv6(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name
|
||||
ep.SocketOptions().SetV6Only(v != 0)
|
||||
return nil
|
||||
|
||||
case linux.IPV6_ADD_MEMBERSHIP,
|
||||
linux.IPV6_DROP_MEMBERSHIP,
|
||||
linux.IPV6_IPSEC_POLICY,
|
||||
case linux.IPV6_ADD_MEMBERSHIP:
|
||||
req, err := copyInMulticastV6Request(optVal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(&tcpip.AddMembershipOption{
|
||||
NIC: tcpip.NICID(req.InterfaceIndex),
|
||||
MulticastAddr: tcpip.Address(req.MulticastAddr[:]),
|
||||
}))
|
||||
|
||||
case linux.IPV6_DROP_MEMBERSHIP:
|
||||
req, err := copyInMulticastV6Request(optVal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(&tcpip.RemoveMembershipOption{
|
||||
NIC: tcpip.NICID(req.InterfaceIndex),
|
||||
MulticastAddr: tcpip.Address(req.MulticastAddr[:]),
|
||||
}))
|
||||
|
||||
case linux.IPV6_IPSEC_POLICY,
|
||||
linux.IPV6_JOIN_ANYCAST,
|
||||
linux.IPV6_LEAVE_ANYCAST,
|
||||
// TODO(b/148887420): Add support for IPV6_PKTINFO.
|
||||
@@ -2181,6 +2201,7 @@ func setSockOptIPv6(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name
|
||||
var (
|
||||
inetMulticastRequestSize = int(binary.Size(linux.InetMulticastRequest{}))
|
||||
inetMulticastRequestWithNICSize = int(binary.Size(linux.InetMulticastRequestWithNIC{}))
|
||||
inet6MulticastRequestSize = int(binary.Size(linux.Inet6MulticastRequest{}))
|
||||
)
|
||||
|
||||
// copyInMulticastRequest copies in a variable-size multicast request. The
|
||||
@@ -2214,6 +2235,16 @@ func copyInMulticastRequest(optVal []byte, allowAddr bool) (linux.InetMulticastR
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func copyInMulticastV6Request(optVal []byte) (linux.Inet6MulticastRequest, *syserr.Error) {
|
||||
if len(optVal) < inet6MulticastRequestSize {
|
||||
return linux.Inet6MulticastRequest{}, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var req linux.Inet6MulticastRequest
|
||||
binary.Unmarshal(optVal[:inet6MulticastRequestSize], usermem.ByteOrder, &req)
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// parseIntOrChar copies either a 32-bit int or an 8-bit uint out of buf.
|
||||
//
|
||||
// net/ipv4/ip_sockglue.c:do_ip_setsockopt does this for its socket options.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -708,14 +708,9 @@ func (e *endpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error {
|
||||
|
||||
nicID := v.NIC
|
||||
|
||||
// The interface address is considered not-set if it is empty or contains
|
||||
// all-zeros. The former represent the zero-value in golang, the latter the
|
||||
// same in a setsockopt(IP_ADD_MEMBERSHIP, &ip_mreqn) syscall.
|
||||
allZeros := header.IPv4Any
|
||||
if len(v.InterfaceAddr) == 0 || v.InterfaceAddr == allZeros {
|
||||
if v.InterfaceAddr.Unspecified() {
|
||||
if nicID == 0 {
|
||||
r, err := e.stack.FindRoute(0, "", v.MulticastAddr, header.IPv4ProtocolNumber, false /* multicastLoop */)
|
||||
if err == nil {
|
||||
if r, err := e.stack.FindRoute(0, "", v.MulticastAddr, e.NetProto, false /* multicastLoop */); err == nil {
|
||||
nicID = r.NICID()
|
||||
r.Release()
|
||||
}
|
||||
@@ -748,10 +743,9 @@ func (e *endpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error {
|
||||
}
|
||||
|
||||
nicID := v.NIC
|
||||
if v.InterfaceAddr == header.IPv4Any {
|
||||
if v.InterfaceAddr.Unspecified() {
|
||||
if nicID == 0 {
|
||||
r, err := e.stack.FindRoute(0, "", v.MulticastAddr, header.IPv4ProtocolNumber, false /* multicastLoop */)
|
||||
if err == nil {
|
||||
if r, err := e.stack.FindRoute(0, "", v.MulticastAddr, e.NetProto, false /* multicastLoop */); err == nil {
|
||||
nicID = r.NICID()
|
||||
r.Release()
|
||||
}
|
||||
|
||||
@@ -681,6 +681,11 @@ syscall_test(
|
||||
test = "//test/syscalls/linux:socket_ipv4_udp_unbound_loopback_test",
|
||||
)
|
||||
|
||||
syscall_test(
|
||||
size = "medium",
|
||||
test = "//test/syscalls/linux:socket_ipv6_udp_unbound_loopback_test",
|
||||
)
|
||||
|
||||
syscall_test(
|
||||
size = "medium",
|
||||
add_hostinet = True,
|
||||
|
||||
@@ -20,6 +20,7 @@ exports_files(
|
||||
"socket_ip_udp_loopback_nonblock.cc",
|
||||
"socket_ip_unbound.cc",
|
||||
"socket_ipv4_udp_unbound_external_networking_test.cc",
|
||||
"socket_ipv6_udp_unbound_external_networking_test.cc",
|
||||
"socket_ipv4_udp_unbound_loopback.cc",
|
||||
"socket_ipv6_udp_unbound_loopback.cc",
|
||||
"socket_ipv4_udp_unbound_loopback_nogotsan.cc",
|
||||
@@ -2510,6 +2511,23 @@ cc_library(
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "socket_ip_udp_unbound_external_networking",
|
||||
testonly = 1,
|
||||
srcs = [
|
||||
"socket_ip_udp_unbound_external_networking.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"socket_ip_udp_unbound_external_networking.h",
|
||||
],
|
||||
deps = [
|
||||
":ip_socket_test_util",
|
||||
":socket_test_util",
|
||||
"//test/util:test_util",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "socket_ipv4_udp_unbound_external_networking_test_cases",
|
||||
testonly = 1,
|
||||
@@ -2520,10 +2538,24 @@ cc_library(
|
||||
"socket_ipv4_udp_unbound_external_networking.h",
|
||||
],
|
||||
deps = [
|
||||
":ip_socket_test_util",
|
||||
":socket_test_util",
|
||||
":socket_ip_udp_unbound_external_networking",
|
||||
gtest,
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "socket_ipv6_udp_unbound_external_networking_test_cases",
|
||||
testonly = 1,
|
||||
srcs = [
|
||||
"socket_ipv6_udp_unbound_external_networking.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"socket_ipv6_udp_unbound_external_networking.h",
|
||||
],
|
||||
deps = [
|
||||
":socket_ip_udp_unbound_external_networking",
|
||||
gtest,
|
||||
"//test/util:test_util",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
@@ -2722,6 +2754,22 @@ cc_binary(
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "socket_ipv6_udp_unbound_external_networking_test",
|
||||
testonly = 1,
|
||||
srcs = [
|
||||
"socket_ipv6_udp_unbound_external_networking_test.cc",
|
||||
],
|
||||
linkstatic = 1,
|
||||
deps = [
|
||||
":ip_socket_test_util",
|
||||
":socket_ipv6_udp_unbound_external_networking_test_cases",
|
||||
":socket_test_util",
|
||||
"//test/util:test_main",
|
||||
"//test/util:test_util",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "socket_bind_to_device_test",
|
||||
testonly = 1,
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "test/syscalls/linux/socket_ip_udp_unbound_external_networking.h"
|
||||
|
||||
#include "test/syscalls/linux/socket_test_util.h"
|
||||
#include "test/util/test_util.h"
|
||||
|
||||
namespace gvisor {
|
||||
namespace testing {
|
||||
|
||||
void IPUDPUnboundExternalNetworkingSocketTest::SetUp() {
|
||||
// FIXME(b/137899561): Linux instance for syscall tests sometimes misses its
|
||||
// IPv4 address on eth0.
|
||||
found_net_interfaces_ = false;
|
||||
|
||||
// Get interface list.
|
||||
ASSERT_NO_ERRNO(if_helper_.Load());
|
||||
std::vector<std::string> if_names = if_helper_.InterfaceList(AF_INET);
|
||||
if (if_names.size() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out which interface is where.
|
||||
std::string lo = if_names[0];
|
||||
std::string eth = if_names[1];
|
||||
if (lo != "lo") std::swap(lo, eth);
|
||||
if (lo != "lo") return;
|
||||
|
||||
lo_if_idx_ = ASSERT_NO_ERRNO_AND_VALUE(if_helper_.GetIndex(lo));
|
||||
auto lo_if_addr = if_helper_.GetAddr(AF_INET, lo);
|
||||
if (lo_if_addr == nullptr) {
|
||||
return;
|
||||
}
|
||||
lo_if_addr_ = *reinterpret_cast<const sockaddr_in*>(lo_if_addr);
|
||||
|
||||
eth_if_idx_ = ASSERT_NO_ERRNO_AND_VALUE(if_helper_.GetIndex(eth));
|
||||
auto eth_if_addr = if_helper_.GetAddr(AF_INET, eth);
|
||||
if (eth_if_addr == nullptr) {
|
||||
return;
|
||||
}
|
||||
eth_if_addr_ = *reinterpret_cast<const sockaddr_in*>(eth_if_addr);
|
||||
|
||||
found_net_interfaces_ = true;
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace gvisor
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IP_UDP_UNBOUND_EXTERNAL_NETWORKING_H_
|
||||
#define GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IP_UDP_UNBOUND_EXTERNAL_NETWORKING_H_
|
||||
|
||||
#include "test/syscalls/linux/ip_socket_test_util.h"
|
||||
#include "test/syscalls/linux/socket_test_util.h"
|
||||
|
||||
namespace gvisor {
|
||||
namespace testing {
|
||||
|
||||
// Test fixture for tests that apply to unbound IP UDP sockets in a sandbox
|
||||
// with external networking support.
|
||||
class IPUDPUnboundExternalNetworkingSocketTest : public SimpleSocketTest {
|
||||
protected:
|
||||
void SetUp() override;
|
||||
|
||||
IfAddrHelper if_helper_;
|
||||
|
||||
// found_net_interfaces_ is set to false if SetUp() could not obtain
|
||||
// all interface infos that we need.
|
||||
bool found_net_interfaces_;
|
||||
|
||||
// Interface infos.
|
||||
int lo_if_idx_;
|
||||
int eth_if_idx_;
|
||||
sockaddr_in lo_if_addr_;
|
||||
sockaddr_in eth_if_addr_;
|
||||
};
|
||||
|
||||
} // namespace testing
|
||||
} // namespace gvisor
|
||||
|
||||
#endif // GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IP_UDP_UNBOUND_EXTERNAL_NETWORKING_H_
|
||||
@@ -14,23 +14,6 @@
|
||||
|
||||
#include "test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/syscalls/linux/ip_socket_test_util.h"
|
||||
#include "test/syscalls/linux/socket_test_util.h"
|
||||
#include "test/util/test_util.h"
|
||||
|
||||
namespace gvisor {
|
||||
namespace testing {
|
||||
|
||||
@@ -41,41 +24,6 @@ TestAddress V4EmptyAddress() {
|
||||
return t;
|
||||
}
|
||||
|
||||
void IPv4UDPUnboundExternalNetworkingSocketTest::SetUp() {
|
||||
// FIXME(b/137899561): Linux instance for syscall tests sometimes misses its
|
||||
// IPv4 address on eth0.
|
||||
found_net_interfaces_ = false;
|
||||
|
||||
// Get interface list.
|
||||
ASSERT_NO_ERRNO(if_helper_.Load());
|
||||
std::vector<std::string> if_names = if_helper_.InterfaceList(AF_INET);
|
||||
if (if_names.size() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out which interface is where.
|
||||
std::string lo = if_names[0];
|
||||
std::string eth = if_names[1];
|
||||
if (lo != "lo") std::swap(lo, eth);
|
||||
if (lo != "lo") return;
|
||||
|
||||
lo_if_idx_ = ASSERT_NO_ERRNO_AND_VALUE(if_helper_.GetIndex(lo));
|
||||
auto lo_if_addr = if_helper_.GetAddr(AF_INET, lo);
|
||||
if (lo_if_addr == nullptr) {
|
||||
return;
|
||||
}
|
||||
lo_if_addr_ = *reinterpret_cast<const sockaddr_in*>(lo_if_addr);
|
||||
|
||||
eth_if_idx_ = ASSERT_NO_ERRNO_AND_VALUE(if_helper_.GetIndex(eth));
|
||||
auto eth_if_addr = if_helper_.GetAddr(AF_INET, eth);
|
||||
if (eth_if_addr == nullptr) {
|
||||
return;
|
||||
}
|
||||
eth_if_addr_ = *reinterpret_cast<const sockaddr_in*>(eth_if_addr);
|
||||
|
||||
found_net_interfaces_ = true;
|
||||
}
|
||||
|
||||
// Verifies that a broadcast UDP packet will arrive at all UDP sockets with
|
||||
// the destination port number.
|
||||
TEST_P(IPv4UDPUnboundExternalNetworkingSocketTest,
|
||||
|
||||
@@ -15,30 +15,15 @@
|
||||
#ifndef GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IPV4_UDP_UNBOUND_EXTERNAL_NETWORKING_H_
|
||||
#define GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IPV4_UDP_UNBOUND_EXTERNAL_NETWORKING_H_
|
||||
|
||||
#include "test/syscalls/linux/ip_socket_test_util.h"
|
||||
#include "test/syscalls/linux/socket_test_util.h"
|
||||
#include "test/syscalls/linux/socket_ip_udp_unbound_external_networking.h"
|
||||
|
||||
namespace gvisor {
|
||||
namespace testing {
|
||||
|
||||
// Test fixture for tests that apply to unbound IPv4 UDP sockets in a sandbox
|
||||
// with external networking support.
|
||||
class IPv4UDPUnboundExternalNetworkingSocketTest : public SimpleSocketTest {
|
||||
protected:
|
||||
void SetUp();
|
||||
|
||||
IfAddrHelper if_helper_;
|
||||
|
||||
// found_net_interfaces_ is set to false if SetUp() could not obtain
|
||||
// all interface infos that we need.
|
||||
bool found_net_interfaces_;
|
||||
|
||||
// Interface infos.
|
||||
int lo_if_idx_;
|
||||
int eth_if_idx_;
|
||||
sockaddr_in lo_if_addr_;
|
||||
sockaddr_in eth_if_addr_;
|
||||
};
|
||||
using IPv4UDPUnboundExternalNetworkingSocketTest =
|
||||
IPUDPUnboundExternalNetworkingSocketTest;
|
||||
|
||||
} // namespace testing
|
||||
} // namespace gvisor
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.h"
|
||||
|
||||
namespace gvisor {
|
||||
namespace testing {
|
||||
|
||||
TEST_P(IPv6UDPUnboundExternalNetworkingSocketTest, TestJoinLeaveMulticast) {
|
||||
SKIP_IF(!found_net_interfaces_);
|
||||
|
||||
auto sender = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
|
||||
auto receiver = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
|
||||
|
||||
auto receiver_addr = V6Any();
|
||||
ASSERT_THAT(
|
||||
bind(receiver->get(), reinterpret_cast<sockaddr*>(&receiver_addr.addr),
|
||||
receiver_addr.addr_len),
|
||||
SyscallSucceeds());
|
||||
socklen_t receiver_addr_len = receiver_addr.addr_len;
|
||||
ASSERT_THAT(getsockname(receiver->get(),
|
||||
reinterpret_cast<sockaddr*>(&receiver_addr.addr),
|
||||
&receiver_addr_len),
|
||||
SyscallSucceeds());
|
||||
EXPECT_EQ(receiver_addr_len, receiver_addr.addr_len);
|
||||
|
||||
// Register to receive multicast packets.
|
||||
auto multicast_addr = V6Multicast();
|
||||
ipv6_mreq group_req = {
|
||||
.ipv6mr_multiaddr =
|
||||
reinterpret_cast<sockaddr_in6*>(&multicast_addr.addr)->sin6_addr,
|
||||
.ipv6mr_interface =
|
||||
(unsigned int)ASSERT_NO_ERRNO_AND_VALUE(InterfaceIndex("lo")),
|
||||
};
|
||||
ASSERT_THAT(setsockopt(receiver->get(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
|
||||
&group_req, sizeof(group_req)),
|
||||
SyscallSucceeds());
|
||||
|
||||
// Set the sender to the loopback interface.
|
||||
auto sender_addr = V6Loopback();
|
||||
ASSERT_THAT(
|
||||
bind(sender->get(), reinterpret_cast<sockaddr*>(&sender_addr.addr),
|
||||
sender_addr.addr_len),
|
||||
SyscallSucceeds());
|
||||
|
||||
// Send a multicast packet.
|
||||
auto send_addr = multicast_addr;
|
||||
reinterpret_cast<sockaddr_in6*>(&send_addr.addr)->sin6_port =
|
||||
reinterpret_cast<sockaddr_in6*>(&receiver_addr.addr)->sin6_port;
|
||||
char send_buf[200];
|
||||
RandomizeBuffer(send_buf, sizeof(send_buf));
|
||||
ASSERT_THAT(RetryEINTR(sendto)(sender->get(), send_buf, sizeof(send_buf), 0,
|
||||
reinterpret_cast<sockaddr*>(&send_addr.addr),
|
||||
send_addr.addr_len),
|
||||
SyscallSucceedsWithValue(sizeof(send_buf)));
|
||||
|
||||
// Check that we received the multicast packet.
|
||||
char recv_buf[sizeof(send_buf)] = {};
|
||||
ASSERT_THAT(RetryEINTR(recv)(receiver->get(), recv_buf, sizeof(recv_buf), 0),
|
||||
SyscallSucceedsWithValue(sizeof(recv_buf)));
|
||||
|
||||
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
|
||||
|
||||
// Leave the group and make sure we don't receive its multicast traffic.
|
||||
ASSERT_THAT(setsockopt(receiver->get(), IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
|
||||
&group_req, sizeof(group_req)),
|
||||
SyscallSucceeds());
|
||||
RandomizeBuffer(send_buf, sizeof(send_buf));
|
||||
ASSERT_THAT(RetryEINTR(sendto)(sender->get(), send_buf, sizeof(send_buf), 0,
|
||||
reinterpret_cast<sockaddr*>(&send_addr.addr),
|
||||
send_addr.addr_len),
|
||||
SyscallSucceedsWithValue(sizeof(send_buf)));
|
||||
ASSERT_THAT(RetryEINTR(recv)(receiver->get(), recv_buf, sizeof(recv_buf),
|
||||
MSG_DONTWAIT),
|
||||
SyscallFailsWithErrno(EAGAIN));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace gvisor
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IPV6_UDP_UNBOUND_EXTERNAL_NETWORKING_H_
|
||||
#define GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IPV6_UDP_UNBOUND_EXTERNAL_NETWORKING_H_
|
||||
|
||||
#include "test/syscalls/linux/socket_ip_udp_unbound_external_networking.h"
|
||||
|
||||
namespace gvisor {
|
||||
namespace testing {
|
||||
|
||||
// Test fixture for tests that apply to unbound IPv6 UDP sockets in a sandbox
|
||||
// with external networking support.
|
||||
using IPv6UDPUnboundExternalNetworkingSocketTest =
|
||||
IPUDPUnboundExternalNetworkingSocketTest;
|
||||
|
||||
} // namespace testing
|
||||
} // namespace gvisor
|
||||
|
||||
#endif // GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IPV6yy_UDP_UNBOUND_EXTERNAL_NETWORKING_H_
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "test/syscalls/linux/ip_socket_test_util.h"
|
||||
#include "test/syscalls/linux/socket_test_util.h"
|
||||
#include "test/util/test_util.h"
|
||||
|
||||
namespace gvisor {
|
||||
namespace testing {
|
||||
namespace {
|
||||
|
||||
std::vector<SocketKind> GetSockets() {
|
||||
return ApplyVec<SocketKind>(
|
||||
IPv6UDPUnboundSocket,
|
||||
AllBitwiseCombinations(List<int>{0, SOCK_NONBLOCK}));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(IPv6UDPUnboundSockets,
|
||||
IPv6UDPUnboundExternalNetworkingSocketTest,
|
||||
::testing::ValuesIn(GetSockets()));
|
||||
|
||||
} // namespace
|
||||
} // namespace testing
|
||||
} // namespace gvisor
|
||||
@@ -860,6 +860,17 @@ TestAddress V6Loopback() {
|
||||
return t;
|
||||
}
|
||||
|
||||
TestAddress V6Multicast() {
|
||||
TestAddress t("V6Multicast");
|
||||
t.addr.ss_family = AF_INET6;
|
||||
t.addr_len = sizeof(sockaddr_in6);
|
||||
EXPECT_EQ(
|
||||
1,
|
||||
inet_pton(AF_INET6, "ff05::1234",
|
||||
reinterpret_cast<sockaddr_in6*>(&t.addr)->sin6_addr.s6_addr));
|
||||
return t;
|
||||
}
|
||||
|
||||
// Checksum computes the internet checksum of a buffer.
|
||||
uint16_t Checksum(uint16_t* buf, ssize_t buf_size) {
|
||||
// Add up the 16-bit values in the buffer.
|
||||
|
||||
@@ -502,6 +502,7 @@ TestAddress V4MappedLoopback();
|
||||
TestAddress V4Multicast();
|
||||
TestAddress V6Any();
|
||||
TestAddress V6Loopback();
|
||||
TestAddress V6Multicast();
|
||||
|
||||
// Compute the internet checksum of an IP header.
|
||||
uint16_t IPChecksum(struct iphdr ip);
|
||||
|
||||
Reference in New Issue
Block a user