diff options
Diffstat (limited to 'test/syscalls')
-rw-r--r-- | test/syscalls/BUILD | 192 | ||||
-rw-r--r-- | test/syscalls/linux/socket_ipv4_udp_unbound.cc | 100 |
2 files changed, 100 insertions, 192 deletions
diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD index a31612b41..571785ad2 100644 --- a/test/syscalls/BUILD +++ b/test/syscalls/BUILD @@ -4,75 +4,62 @@ package(licenses = ["notice"]) syscall_test( test = "//test/syscalls/linux:32bit_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:accept_bind_stream_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 50, test = "//test/syscalls/linux:accept_bind_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:access_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:affinity_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:aio_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 5, test = "//test/syscalls/linux:alarm_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:arch_prctl_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:bad_test", - vfs2 = "True", ) syscall_test( size = "large", add_overlay = True, test = "//test/syscalls/linux:bind_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:brk_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_capability_test", - vfs2 = "True", ) syscall_test( @@ -82,19 +69,16 @@ syscall_test( # involve much concurrency, TSAN's usefulness here is limited anyway. tags = ["nogotsan"], test = "//test/syscalls/linux:socket_stress_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:chdir_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:chmod_test", - vfs2 = "True", ) syscall_test( @@ -102,116 +86,96 @@ syscall_test( add_overlay = True, test = "//test/syscalls/linux:chown_test", use_tmpfs = True, # chwon tests require gofer to be running as root. - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:chroot_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:clock_getres_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:clock_gettime_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:clock_nanosleep_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:concurrency_test", - vfs2 = "True", ) syscall_test( add_uds_tree = True, test = "//test/syscalls/linux:connect_external_test", use_tmpfs = True, - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:creat_test", - vfs2 = "True", ) syscall_test( fuse = "True", test = "//test/syscalls/linux:dev_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:dup_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:epoll_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:eventfd_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:exceptions_test", - vfs2 = "True", ) syscall_test( size = "medium", add_overlay = True, test = "//test/syscalls/linux:exec_test", - vfs2 = "True", ) syscall_test( size = "medium", add_overlay = True, test = "//test/syscalls/linux:exec_binary_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:exit_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:fadvise64_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:fallocate_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:fault_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:fchdir_test", - vfs2 = "True", ) syscall_test( @@ -223,204 +187,168 @@ syscall_test( size = "medium", add_overlay = True, test = "//test/syscalls/linux:flock_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:fork_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:fpsig_fork_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:fpsig_nested_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:fsync_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 5, test = "//test/syscalls/linux:futex_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:getcpu_host_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:getcpu_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:getdents_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:getrandom_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:getrusage_test", - vfs2 = "True", ) syscall_test( size = "medium", add_overlay = False, # TODO(gvisor.dev/issue/317): enable when fixed. test = "//test/syscalls/linux:inotify_test", - vfs2 = "True", ) syscall_test( size = "medium", add_overlay = True, test = "//test/syscalls/linux:ioctl_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:iptables_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 5, test = "//test/syscalls/linux:itimer_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:kill_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:link_test", use_tmpfs = True, # gofer needs CAP_DAC_READ_SEARCH to use AT_EMPTY_PATH with linkat(2) - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:lseek_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:madvise_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:memory_accounting_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:mempolicy_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:mincore_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:mkdir_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:mknod_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 5, test = "//test/syscalls/linux:mmap_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:mount_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:mremap_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:msync_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:munmap_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:network_namespace_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:open_create_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:open_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:packet_socket_raw_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:packet_socket_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:partial_bad_buffer_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:pause_test", - vfs2 = "True", ) syscall_test( @@ -428,7 +356,6 @@ syscall_test( # Takes too long under gotsan to run. tags = ["nogotsan"], test = "//test/syscalls/linux:ping_socket_test", - vfs2 = "True", ) syscall_test( @@ -436,229 +363,188 @@ syscall_test( add_overlay = True, shard_count = 5, test = "//test/syscalls/linux:pipe_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:poll_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:ppoll_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:prctl_setuid_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:prctl_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:pread64_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:preadv_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:preadv2_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:priority_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:proc_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:proc_net_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:proc_pid_oomscore_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:proc_pid_smaps_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:proc_pid_uid_gid_map_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:pselect_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:ptrace_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 5, test = "//test/syscalls/linux:pty_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:pty_root_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:pwritev2_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:pwrite64_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:raw_socket_hdrincl_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:raw_socket_icmp_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:raw_socket_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:read_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:readahead_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 5, test = "//test/syscalls/linux:readv_socket_test", - vfs2 = "True", ) syscall_test( size = "medium", add_overlay = True, test = "//test/syscalls/linux:readv_test", - vfs2 = "True", ) syscall_test( size = "medium", add_overlay = True, test = "//test/syscalls/linux:rename_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:rlimits_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:rseq_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:rtsignal_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:signalfd_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:sched_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:sched_yield_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:seccomp_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:select_test", - vfs2 = "True", ) syscall_test( shard_count = 20, test = "//test/syscalls/linux:semaphore_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:sendfile_socket_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:sendfile_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:splice_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:sigaction_test", - vfs2 = "True", ) # TODO(b/119826902): Enable once the test passes in runsc. @@ -666,62 +552,52 @@ syscall_test( syscall_test( test = "//test/syscalls/linux:sigiret_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:sigprocmask_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:sigstop_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:sigtimedwait_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:shm_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_abstract_non_blocking_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 50, test = "//test/syscalls/linux:socket_abstract_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_domain_non_blocking_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 50, test = "//test/syscalls/linux:socket_domain_test", - vfs2 = "True", ) syscall_test( size = "medium", add_overlay = True, test = "//test/syscalls/linux:socket_filesystem_non_blocking_test", - vfs2 = "True", ) syscall_test( @@ -729,14 +605,12 @@ syscall_test( add_overlay = True, shard_count = 50, test = "//test/syscalls/linux:socket_filesystem_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 50, test = "//test/syscalls/linux:socket_inet_loopback_test", - vfs2 = "True", ) syscall_test( @@ -745,122 +619,101 @@ syscall_test( # Takes too long for TSAN. Creates a lot of TCP sockets. tags = ["nogotsan"], test = "//test/syscalls/linux:socket_inet_loopback_nogotsan_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 50, test = "//test/syscalls/linux:socket_ip_tcp_generic_loopback_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_ip_tcp_loopback_non_blocking_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 50, test = "//test/syscalls/linux:socket_ip_tcp_loopback_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 50, test = "//test/syscalls/linux:socket_ip_tcp_udp_generic_loopback_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_ip_udp_loopback_non_blocking_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 50, test = "//test/syscalls/linux:socket_ip_udp_loopback_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_ipv4_udp_unbound_loopback_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_ip_unbound_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_netdevice_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_netlink_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_netlink_route_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_netlink_uevent_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_blocking_local_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_blocking_ip_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_non_stream_blocking_local_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:socket_non_stream_blocking_udp_test", - vfs2 = "True", ) syscall_test( size = "large", test = "//test/syscalls/linux:socket_stream_blocking_local_test", - vfs2 = "True", ) syscall_test( size = "large", test = "//test/syscalls/linux:socket_stream_blocking_tcp_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_stream_local_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_stream_nonblock_local_test", - vfs2 = "True", ) syscall_test( @@ -868,13 +721,11 @@ syscall_test( size = "enormous", shard_count = 5, test = "//test/syscalls/linux:socket_unix_dgram_local_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_unix_dgram_non_blocking_test", - vfs2 = "True", ) syscall_test( @@ -882,7 +733,6 @@ syscall_test( add_overlay = True, shard_count = 50, test = "//test/syscalls/linux:socket_unix_pair_test", - vfs2 = "True", ) syscall_test( @@ -890,156 +740,129 @@ syscall_test( size = "enormous", shard_count = 5, test = "//test/syscalls/linux:socket_unix_seqpacket_local_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_unix_stream_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_unix_unbound_abstract_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_unix_unbound_dgram_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:socket_unix_unbound_filesystem_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 10, test = "//test/syscalls/linux:socket_unix_unbound_seqpacket_test", - vfs2 = "True", ) syscall_test( size = "large", shard_count = 50, test = "//test/syscalls/linux:socket_unix_unbound_stream_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:statfs_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:stat_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:stat_times_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:sticky_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:symlink_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:sync_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:sync_file_range_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:sysinfo_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:syslog_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:sysret_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 10, test = "//test/syscalls/linux:tcp_socket_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:tgkill_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:timerfd_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:timers_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:time_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:tkill_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:truncate_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:tuntap_test", - vfs2 = "True", ) syscall_test( add_hostinet = True, test = "//test/syscalls/linux:tuntap_hostinet_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:udp_bind_test", - vfs2 = "True", ) syscall_test( @@ -1047,80 +870,65 @@ syscall_test( add_hostinet = True, shard_count = 10, test = "//test/syscalls/linux:udp_socket_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:uidgid_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:uname_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:unlink_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:unshare_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:utimes_test", - vfs2 = "True", ) syscall_test( size = "medium", test = "//test/syscalls/linux:vdso_clock_gettime_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:vdso_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:vsyscall_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:vfork_test", - vfs2 = "True", ) syscall_test( size = "medium", shard_count = 5, test = "//test/syscalls/linux:wait_test", - vfs2 = "True", ) syscall_test( add_overlay = True, test = "//test/syscalls/linux:write_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:proc_net_unix_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:proc_net_tcp_test", - vfs2 = "True", ) syscall_test( test = "//test/syscalls/linux:proc_net_udp_test", - vfs2 = "True", ) diff --git a/test/syscalls/linux/socket_ipv4_udp_unbound.cc b/test/syscalls/linux/socket_ipv4_udp_unbound.cc index de0f5f01b..bc005e2bb 100644 --- a/test/syscalls/linux/socket_ipv4_udp_unbound.cc +++ b/test/syscalls/linux/socket_ipv4_udp_unbound.cc @@ -2452,5 +2452,105 @@ TEST_P(IPv4UDPUnboundSocketTest, SetSocketSendBuf) { ASSERT_EQ(quarter_sz, val); } + +TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIPPacketInfo) { + auto sender_socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); + auto receiver_socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); + + // Bind the first FD to the loopback. This is an alternative to + // IP_MULTICAST_IF for setting the default send interface. + auto sender_addr = V4Loopback(); + ASSERT_THAT( + bind(sender_socket->get(), reinterpret_cast<sockaddr*>(&sender_addr.addr), + sender_addr.addr_len), + SyscallSucceeds()); + + // Bind the second FD to the v4 any address to ensure that we can receive the + // multicast packet. + auto receiver_addr = V4Any(); + ASSERT_THAT(bind(receiver_socket->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_socket->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. + ip_mreqn group = {}; + group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress); + group.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(InterfaceIndex("lo")); + ASSERT_THAT(setsockopt(receiver_socket->get(), IPPROTO_IP, IP_ADD_MEMBERSHIP, + &group, sizeof(group)), + SyscallSucceeds()); + + // Register to receive IP packet info. + const int one = 1; + ASSERT_THAT(setsockopt(receiver_socket->get(), IPPROTO_IP, IP_PKTINFO, &one, + sizeof(one)), + SyscallSucceeds()); + + // Send a multicast packet. + auto send_addr = V4Multicast(); + reinterpret_cast<sockaddr_in*>(&send_addr.addr)->sin_port = + reinterpret_cast<sockaddr_in*>(&receiver_addr.addr)->sin_port; + char send_buf[200]; + RandomizeBuffer(send_buf, sizeof(send_buf)); + ASSERT_THAT( + RetryEINTR(sendto)(sender_socket->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. + msghdr recv_msg = {}; + iovec recv_iov = {}; + char recv_buf[sizeof(send_buf)]; + char recv_cmsg_buf[CMSG_SPACE(sizeof(in_pktinfo))] = {}; + size_t cmsg_data_len = sizeof(in_pktinfo); + recv_iov.iov_base = recv_buf; + recv_iov.iov_len = sizeof(recv_buf); + recv_msg.msg_iov = &recv_iov; + recv_msg.msg_iovlen = 1; + recv_msg.msg_controllen = CMSG_LEN(cmsg_data_len); + recv_msg.msg_control = recv_cmsg_buf; + ASSERT_THAT(RetryEINTR(recvmsg)(receiver_socket->get(), &recv_msg, 0), + SyscallSucceedsWithValue(sizeof(send_buf))); + EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf))); + + // Check the IP_PKTINFO control message. + cmsghdr* cmsg = CMSG_FIRSTHDR(&recv_msg); + ASSERT_NE(cmsg, nullptr); + EXPECT_EQ(cmsg->cmsg_len, CMSG_LEN(cmsg_data_len)); + EXPECT_EQ(cmsg->cmsg_level, IPPROTO_IP); + EXPECT_EQ(cmsg->cmsg_type, IP_PKTINFO); + + // Get loopback index. + ifreq ifr = {}; + absl::SNPrintF(ifr.ifr_name, IFNAMSIZ, "lo"); + ASSERT_THAT(ioctl(receiver_socket->get(), SIOCGIFINDEX, &ifr), + SyscallSucceeds()); + ASSERT_NE(ifr.ifr_ifindex, 0); + + in_pktinfo received_pktinfo = {}; + memcpy(&received_pktinfo, CMSG_DATA(cmsg), sizeof(in_pktinfo)); + EXPECT_EQ(received_pktinfo.ipi_ifindex, ifr.ifr_ifindex); + if (IsRunningOnGvisor()) { + // This should actually be a unicast address assigned to the interface. + // + // TODO(gvisor.dev/issue/3556): This check is validating incorrect + // behaviour. We still include the test so that once the bug is + // resolved, this test will start to fail and the individual tasked + // with fixing this bug knows to also fix this test :). + EXPECT_EQ(received_pktinfo.ipi_spec_dst.s_addr, group.imr_multiaddr.s_addr); + } else { + EXPECT_EQ(received_pktinfo.ipi_spec_dst.s_addr, htonl(INADDR_LOOPBACK)); + } + EXPECT_EQ(received_pktinfo.ipi_addr.s_addr, group.imr_multiaddr.s_addr); +} + } // namespace testing } // namespace gvisor |