summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls
diff options
context:
space:
mode:
authorGhanan Gowripalan <ghanan@google.com>2021-01-06 11:39:14 -0800
committergVisor bot <gvisor-bot@google.com>2021-01-06 11:41:42 -0800
commitabe9d9f67f2c2c696ef26690fa8518dfc4e28728 (patch)
treeeabba6c15b22345ab322f7380548c4c8eb5e50fe /test/syscalls
parent0c4118d5b8428648c252df55a7867ac6f287f146 (diff)
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
Diffstat (limited to 'test/syscalls')
-rw-r--r--test/syscalls/BUILD5
-rw-r--r--test/syscalls/linux/BUILD54
-rw-r--r--test/syscalls/linux/socket_ip_udp_unbound_external_networking.cc59
-rw-r--r--test/syscalls/linux/socket_ip_udp_unbound_external_networking.h46
-rw-r--r--test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc52
-rw-r--r--test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.h21
-rw-r--r--test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.cc90
-rw-r--r--test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.h31
-rw-r--r--test/syscalls/linux/socket_ipv6_udp_unbound_external_networking_test.cc39
-rw-r--r--test/syscalls/linux/socket_test_util.cc11
-rw-r--r--test/syscalls/linux/socket_test_util.h1
11 files changed, 336 insertions, 73 deletions
diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD
index a5b9233f7..7fe7db5cb 100644
--- a/test/syscalls/BUILD
+++ b/test/syscalls/BUILD
@@ -683,6 +683,11 @@ syscall_test(
syscall_test(
size = "medium",
+ test = "//test/syscalls/linux:socket_ipv6_udp_unbound_loopback_test",
+)
+
+syscall_test(
+ size = "medium",
add_hostinet = True,
shard_count = more_shards,
# Takes too long under gotsan to run.
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD
index 4e0c8a574..017f997de 100644
--- a/test/syscalls/linux/BUILD
+++ b/test/syscalls/linux/BUILD
@@ -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",
@@ -2511,6 +2512,23 @@ cc_library(
)
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,
srcs = [
@@ -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,
)
@@ -2723,6 +2755,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,
srcs = [
diff --git a/test/syscalls/linux/socket_ip_udp_unbound_external_networking.cc b/test/syscalls/linux/socket_ip_udp_unbound_external_networking.cc
new file mode 100644
index 000000000..fdbb2216b
--- /dev/null
+++ b/test/syscalls/linux/socket_ip_udp_unbound_external_networking.cc
@@ -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
diff --git a/test/syscalls/linux/socket_ip_udp_unbound_external_networking.h b/test/syscalls/linux/socket_ip_udp_unbound_external_networking.h
new file mode 100644
index 000000000..e5287addb
--- /dev/null
+++ b/test/syscalls/linux/socket_ip_udp_unbound_external_networking.h
@@ -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_
diff --git a/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc b/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc
index 2eecb0866..940289d15 100644
--- a/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc
+++ b/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc
@@ -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,
diff --git a/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.h b/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.h
index 0e9e70e8e..20922ac1f 100644
--- a/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.h
+++ b/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.h
@@ -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
diff --git a/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.cc b/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.cc
new file mode 100644
index 000000000..7364a1ea5
--- /dev/null
+++ b/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.cc
@@ -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
diff --git a/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.h b/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.h
new file mode 100644
index 000000000..731ae0a1f
--- /dev/null
+++ b/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.h
@@ -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_
diff --git a/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking_test.cc b/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking_test.cc
new file mode 100644
index 000000000..5c764b8fd
--- /dev/null
+++ b/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking_test.cc
@@ -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
diff --git a/test/syscalls/linux/socket_test_util.cc b/test/syscalls/linux/socket_test_util.cc
index a760581b5..26dacc95e 100644
--- a/test/syscalls/linux/socket_test_util.cc
+++ b/test/syscalls/linux/socket_test_util.cc
@@ -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.
diff --git a/test/syscalls/linux/socket_test_util.h b/test/syscalls/linux/socket_test_util.h
index 5e205339f..75c0d4735 100644
--- a/test/syscalls/linux/socket_test_util.h
+++ b/test/syscalls/linux/socket_test_util.h
@@ -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);