1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #if defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
6 // This must be defined before including any system headers.
7 #define __APPLE_USE_RFC_3542
8 #endif // defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
9
10 #include "quiche/quic/core/quic_udp_socket.h"
11
12 #include "absl/base/optimization.h"
13 #include "quiche/quic/core/io/socket.h"
14 #include "quiche/quic/platform/api/quic_bug_tracker.h"
15 #include "quiche/quic/platform/api/quic_flag_utils.h"
16
17 // Common cmsg-related functions are defined below.
18 // Windows and POSIX cmsg formats are actually fairly similar, except the
19 // Windows ones have all of the macros prefixed with WSA_ and all the type names
20 // are different.
21
22 namespace quic {
23 namespace {
24
25 #if defined(_WIN32)
26 using PlatformCmsghdr = ::WSACMSGHDR;
27 #if !defined(CMSG_DATA)
28 #define CMSG_DATA WSA_CMSG_DATA
29 #endif // !defined(CMSG_DATA)
30 #else
31 using PlatformCmsghdr = ::cmsghdr;
32 #endif // defined(_WIN32)
33
PopulatePacketInfoFromControlMessageBase(PlatformCmsghdr * cmsg,QuicUdpPacketInfo * packet_info,QuicUdpPacketInfoBitMask packet_info_interested)34 void PopulatePacketInfoFromControlMessageBase(
35 PlatformCmsghdr* cmsg, QuicUdpPacketInfo* packet_info,
36 QuicUdpPacketInfoBitMask packet_info_interested) {
37 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
38 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V6_SELF_IP)) {
39 const in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
40 const char* addr_data = reinterpret_cast<const char*>(&info->ipi6_addr);
41 int addr_len = sizeof(in6_addr);
42 QuicIpAddress self_v6_ip;
43 if (self_v6_ip.FromPackedString(addr_data, addr_len)) {
44 packet_info->SetSelfV6Ip(self_v6_ip);
45 } else {
46 QUIC_BUG(quic_bug_10751_1) << "QuicIpAddress::FromPackedString failed";
47 }
48 }
49 return;
50 }
51
52 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
53 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V4_SELF_IP)) {
54 const in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
55 const char* addr_data = reinterpret_cast<const char*>(&info->ipi_addr);
56 int addr_len = sizeof(in_addr);
57 QuicIpAddress self_v4_ip;
58 if (self_v4_ip.FromPackedString(addr_data, addr_len)) {
59 packet_info->SetSelfV4Ip(self_v4_ip);
60 } else {
61 QUIC_BUG(quic_bug_10751_2) << "QuicIpAddress::FromPackedString failed";
62 }
63 }
64 return;
65 }
66 }
67
68 } // namespace
69 } // namespace quic
70
71 #if defined(_WIN32)
72 #include "quiche/quic/core/quic_udp_socket_win.inc"
73 #else
74 #include "quiche/quic/core/quic_udp_socket_posix.inc"
75 #endif
76
77 namespace quic {
78
Create(int address_family,int receive_buffer_size,int send_buffer_size,bool ipv6_only)79 QuicUdpSocketFd QuicUdpSocketApi::Create(int address_family,
80 int receive_buffer_size,
81 int send_buffer_size, bool ipv6_only) {
82 // QUICHE_DCHECK here so the program exits early(before reading packets) in
83 // debug mode. This should have been a static_assert, however it can't be done
84 // on ios/osx because CMSG_SPACE isn't a constant expression there.
85 QUICHE_DCHECK_GE(kDefaultUdpPacketControlBufferSize, kMinCmsgSpaceForRead);
86
87 absl::StatusOr<SocketFd> socket = socket_api::CreateSocket(
88 quiche::FromPlatformAddressFamily(address_family),
89 socket_api::SocketProtocol::kUdp,
90 /*blocking=*/false);
91
92 if (!socket.ok()) {
93 QUIC_LOG_FIRST_N(ERROR, 100)
94 << "UDP non-blocking socket creation for address_family="
95 << address_family << " failed: " << socket.status();
96 return kQuicInvalidSocketFd;
97 }
98
99 #if !defined(_WIN32)
100 SetGoogleSocketOptions(*socket);
101 #endif
102
103 if (!SetupSocket(*socket, address_family, receive_buffer_size,
104 send_buffer_size, ipv6_only)) {
105 Destroy(*socket);
106 return kQuicInvalidSocketFd;
107 }
108
109 return *socket;
110 }
111
Destroy(QuicUdpSocketFd fd)112 void QuicUdpSocketApi::Destroy(QuicUdpSocketFd fd) {
113 if (fd != kQuicInvalidSocketFd) {
114 absl::Status result = socket_api::Close(fd);
115 if (!result.ok()) {
116 QUIC_LOG_FIRST_N(WARNING, 100)
117 << "Failed to close UDP socket with error " << result;
118 }
119 }
120 }
121
Bind(QuicUdpSocketFd fd,QuicSocketAddress address)122 bool QuicUdpSocketApi::Bind(QuicUdpSocketFd fd, QuicSocketAddress address) {
123 sockaddr_storage addr = address.generic_address();
124 int addr_len =
125 address.host().IsIPv4() ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
126 return 0 == bind(fd, reinterpret_cast<sockaddr*>(&addr), addr_len);
127 }
128
BindInterface(QuicUdpSocketFd fd,const std::string & interface_name)129 bool QuicUdpSocketApi::BindInterface(QuicUdpSocketFd fd,
130 const std::string& interface_name) {
131 #if defined(__linux__) && !defined(__ANDROID_API__)
132 if (interface_name.empty() || interface_name.size() >= IFNAMSIZ) {
133 QUIC_BUG(udp_bad_interface_name)
134 << "interface_name must be nonempty and shorter than " << IFNAMSIZ;
135 return false;
136 }
137
138 return 0 == setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
139 interface_name.c_str(), interface_name.length());
140 #else
141 (void)fd;
142 (void)interface_name;
143 QUIC_BUG(interface_bind_not_implemented)
144 << "Interface binding is not implemented on this platform";
145 return false;
146 #endif
147 }
148
EnableDroppedPacketCount(QuicUdpSocketFd fd)149 bool QuicUdpSocketApi::EnableDroppedPacketCount(QuicUdpSocketFd fd) {
150 #if defined(__linux__) && defined(SO_RXQ_OVFL)
151 int get_overflow = 1;
152 return 0 == setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
153 sizeof(get_overflow));
154 #else
155 (void)fd;
156 return false;
157 #endif
158 }
159
EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd)160 bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd) {
161 int get_self_ip = 1;
162 return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO,
163 reinterpret_cast<char*>(&get_self_ip),
164 sizeof(get_self_ip));
165 }
166
EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd)167 bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd) {
168 int get_self_ip = 1;
169 return 0 == setsockopt(fd, IPPROTO_IPV6, kIpv6RecvPacketInfo,
170 reinterpret_cast<char*>(&get_self_ip),
171 sizeof(get_self_ip));
172 }
173
EnableReceiveTimestamp(QuicUdpSocketFd fd)174 bool QuicUdpSocketApi::EnableReceiveTimestamp(QuicUdpSocketFd fd) {
175 #if defined(QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING)
176 int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
177 return 0 == setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, ×tamping,
178 sizeof(timestamping));
179 #else
180 (void)fd;
181 return false;
182 #endif
183 }
184
EnableReceiveTtlForV4(QuicUdpSocketFd fd)185 bool QuicUdpSocketApi::EnableReceiveTtlForV4(QuicUdpSocketFd fd) {
186 #if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
187 int get_ttl = 1;
188 return 0 == setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &get_ttl, sizeof(get_ttl));
189 #else
190 (void)fd;
191 return false;
192 #endif
193 }
194
EnableReceiveTtlForV6(QuicUdpSocketFd fd)195 bool QuicUdpSocketApi::EnableReceiveTtlForV6(QuicUdpSocketFd fd) {
196 #if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
197 int get_ttl = 1;
198 return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &get_ttl,
199 sizeof(get_ttl));
200 #else
201 (void)fd;
202 return false;
203 #endif
204 }
205
206 } // namespace quic
207