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 #include "quiche/quic/core/quic_types.h"
6 #if defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
7 // This must be defined before including any system headers.
8 #define __APPLE_USE_RFC_3542
9 #endif // defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
10
11 #include <arpa/inet.h>
12 #include <fcntl.h>
13 #include <net/if.h>
14 #include <netinet/in.h>
15 #include <sys/select.h>
16 #include <sys/socket.h>
17 #include <sys/types.h>
18
19 #include "absl/base/optimization.h"
20 #include "quiche/quic/core/io/socket.h"
21 #include "quiche/quic/core/quic_udp_socket.h"
22 #include "quiche/quic/platform/api/quic_bug_tracker.h"
23 #include "quiche/quic/platform/api/quic_flag_utils.h"
24 #include "quiche/quic/platform/api/quic_udp_socket_platform_api.h"
25
26 #if defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
27 #error "__APPLE_USE_RFC_3542 needs to be defined."
28 #endif
29
30 #if defined(__linux__)
31 #include <alloca.h>
32 // For SO_TIMESTAMPING.
33 #include <linux/net_tstamp.h>
34 #endif
35
36 #if defined(__linux__) && !defined(__ANDROID__)
37 #define QUIC_UDP_SOCKET_SUPPORT_TTL 1
38 #endif
39
40 namespace quic {
41 namespace {
42
43 // Explicit Congestion Notification is the last two bits of the TOS byte.
44 constexpr uint8_t kEcnMask = 0x03;
45
46 #if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
47 #define QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING 1
48 // This is the structure that SO_TIMESTAMPING fills into the cmsg header.
49 // It is well-defined, but does not have a definition in a public header.
50 // See https://www.kernel.org/doc/Documentation/networking/timestamping.txt
51 // for more information.
52 struct LinuxSoTimestamping {
53 // The converted system time of the timestamp.
54 struct timespec systime;
55 // Deprecated; serves only as padding.
56 struct timespec hwtimetrans;
57 // The raw hardware timestamp.
58 struct timespec hwtimeraw;
59 };
60 const size_t kCmsgSpaceForRecvTimestamp =
61 CMSG_SPACE(sizeof(LinuxSoTimestamping));
62 #else
63 const size_t kCmsgSpaceForRecvTimestamp = 0;
64 #endif
65
66 const size_t kMinCmsgSpaceForRead =
67 CMSG_SPACE(sizeof(uint32_t)) // Dropped packet count
68 + CMSG_SPACE(sizeof(in_pktinfo)) // V4 Self IP
69 + CMSG_SPACE(sizeof(in6_pktinfo)) // V6 Self IP
70 + kCmsgSpaceForRecvTimestamp + CMSG_SPACE(sizeof(int)) // TTL
71 + kCmsgSpaceForGooglePacketHeader;
72
SetV4SelfIpInControlMessage(const QuicIpAddress & self_address,cmsghdr * cmsg)73 void SetV4SelfIpInControlMessage(const QuicIpAddress& self_address,
74 cmsghdr* cmsg) {
75 QUICHE_DCHECK(self_address.IsIPv4());
76 in_pktinfo* pktinfo = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
77 memset(pktinfo, 0, sizeof(in_pktinfo));
78 pktinfo->ipi_ifindex = 0;
79 std::string address_string = self_address.ToPackedString();
80 memcpy(&pktinfo->ipi_spec_dst, address_string.c_str(),
81 address_string.length());
82 }
83
SetV6SelfIpInControlMessage(const QuicIpAddress & self_address,cmsghdr * cmsg)84 void SetV6SelfIpInControlMessage(const QuicIpAddress& self_address,
85 cmsghdr* cmsg) {
86 QUICHE_DCHECK(self_address.IsIPv6());
87 in6_pktinfo* pktinfo = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
88 memset(pktinfo, 0, sizeof(in6_pktinfo));
89 std::string address_string = self_address.ToPackedString();
90 memcpy(&pktinfo->ipi6_addr, address_string.c_str(), address_string.length());
91 }
92
PopulatePacketInfoFromControlMessage(struct cmsghdr * cmsg,QuicUdpPacketInfo * packet_info,BitMask64 packet_info_interested)93 void PopulatePacketInfoFromControlMessage(struct cmsghdr* cmsg,
94 QuicUdpPacketInfo* packet_info,
95 BitMask64 packet_info_interested) {
96 #ifdef SOL_UDP
97 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::IS_GRO) &&
98 cmsg->cmsg_level == SOL_UDP && cmsg->cmsg_type == UDP_GRO) {
99 packet_info->set_gso_size(*reinterpret_cast<uint16_t*>(CMSG_DATA(cmsg)));
100 }
101 #endif
102
103 #if defined(__linux__) && defined(SO_RXQ_OVFL)
104 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL) {
105 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::DROPPED_PACKETS)) {
106 packet_info->SetDroppedPackets(
107 *(reinterpret_cast<uint32_t*> CMSG_DATA(cmsg)));
108 }
109 return;
110 }
111 #endif
112
113 #if defined(QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING)
114 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING) {
115 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::RECV_TIMESTAMP)) {
116 LinuxSoTimestamping* linux_ts =
117 reinterpret_cast<LinuxSoTimestamping*>(CMSG_DATA(cmsg));
118 timespec* ts = &linux_ts->systime;
119 int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) +
120 (static_cast<int64_t>(ts->tv_nsec) / 1000);
121 packet_info->SetReceiveTimestamp(
122 QuicWallTime::FromUNIXMicroseconds(usec));
123 }
124 return;
125 }
126 #endif
127
128 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
129 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V6_SELF_IP)) {
130 const in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
131 const char* addr_data = reinterpret_cast<const char*>(&info->ipi6_addr);
132 int addr_len = sizeof(in6_addr);
133 QuicIpAddress self_v6_ip;
134 if (self_v6_ip.FromPackedString(addr_data, addr_len)) {
135 packet_info->SetSelfV6Ip(self_v6_ip);
136 } else {
137 QUIC_BUG(quic_bug_10751_1) << "QuicIpAddress::FromPackedString failed";
138 }
139 }
140 return;
141 }
142
143 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
144 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V4_SELF_IP)) {
145 const in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
146 const char* addr_data = reinterpret_cast<const char*>(&info->ipi_addr);
147 int addr_len = sizeof(in_addr);
148 QuicIpAddress self_v4_ip;
149 if (self_v4_ip.FromPackedString(addr_data, addr_len)) {
150 packet_info->SetSelfV4Ip(self_v4_ip);
151 } else {
152 QUIC_BUG(quic_bug_10751_2) << "QuicIpAddress::FromPackedString failed";
153 }
154 }
155 return;
156 }
157
158 if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL) ||
159 (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT)) {
160 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::TTL)) {
161 packet_info->SetTtl(*(reinterpret_cast<int*>(CMSG_DATA(cmsg))));
162 }
163 return;
164 }
165
166 if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TOS) ||
167 (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_TCLASS)) {
168 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::ECN)) {
169 packet_info->SetEcnCodepoint(QuicEcnCodepoint(
170 *(reinterpret_cast<uint8_t*>(CMSG_DATA(cmsg))) & kEcnMask));
171 }
172 }
173
174 if (packet_info_interested.IsSet(
175 QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)) {
176 BufferSpan google_packet_headers;
177 if (GetGooglePacketHeadersFromControlMessage(
178 cmsg, &google_packet_headers.buffer,
179 &google_packet_headers.buffer_len)) {
180 packet_info->SetGooglePacketHeaders(google_packet_headers);
181 }
182 }
183 }
184
NextCmsg(msghdr * hdr,char * control_buffer,size_t control_buffer_len,int cmsg_level,int cmsg_type,size_t data_size,cmsghdr ** cmsg)185 bool NextCmsg(msghdr* hdr, char* control_buffer, size_t control_buffer_len,
186 int cmsg_level, int cmsg_type, size_t data_size,
187 cmsghdr** cmsg /*in, out*/) {
188 // msg_controllen needs to be increased first, otherwise CMSG_NXTHDR will
189 // return nullptr.
190 hdr->msg_controllen += CMSG_SPACE(data_size);
191 if (hdr->msg_controllen > control_buffer_len) {
192 return false;
193 }
194
195 if ((*cmsg) == nullptr) {
196 QUICHE_DCHECK_EQ(nullptr, hdr->msg_control);
197 memset(control_buffer, 0, control_buffer_len);
198 hdr->msg_control = control_buffer;
199 (*cmsg) = CMSG_FIRSTHDR(hdr);
200 } else {
201 QUICHE_DCHECK_NE(nullptr, hdr->msg_control);
202 (*cmsg) = CMSG_NXTHDR(hdr, (*cmsg));
203 }
204
205 if (nullptr == (*cmsg)) {
206 return false;
207 }
208
209 (*cmsg)->cmsg_len = CMSG_LEN(data_size);
210 (*cmsg)->cmsg_level = cmsg_level;
211 (*cmsg)->cmsg_type = cmsg_type;
212
213 return true;
214 }
215 } // namespace
216
Create(int address_family,int receive_buffer_size,int send_buffer_size,bool ipv6_only)217 QuicUdpSocketFd QuicUdpSocketApi::Create(int address_family,
218 int receive_buffer_size,
219 int send_buffer_size, bool ipv6_only) {
220 // QUICHE_DCHECK here so the program exits early(before reading packets) in
221 // debug mode. This should have been a static_assert, however it can't be done
222 // on ios/osx because CMSG_SPACE isn't a constant expression there.
223 QUICHE_DCHECK_GE(kDefaultUdpPacketControlBufferSize, kMinCmsgSpaceForRead);
224
225 absl::StatusOr<SocketFd> socket = socket_api::CreateSocket(
226 quiche::FromPlatformAddressFamily(address_family),
227 socket_api::SocketProtocol::kUdp,
228 /*blocking=*/false);
229
230 if (!socket.ok()) {
231 QUIC_LOG_FIRST_N(ERROR, 100)
232 << "UDP non-blocking socket creation for address_family="
233 << address_family << " failed: " << socket.status();
234 return kQuicInvalidSocketFd;
235 }
236
237 SetGoogleSocketOptions(socket.value());
238
239 if (!SetupSocket(socket.value(), address_family, receive_buffer_size,
240 send_buffer_size, ipv6_only)) {
241 Destroy(socket.value());
242 return kQuicInvalidSocketFd;
243 }
244
245 return socket.value();
246 }
247
SetupSocket(QuicUdpSocketFd fd,int address_family,int receive_buffer_size,int send_buffer_size,bool ipv6_only)248 bool QuicUdpSocketApi::SetupSocket(QuicUdpSocketFd fd, int address_family,
249 int receive_buffer_size,
250 int send_buffer_size, bool ipv6_only) {
251 // Receive buffer size.
252 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &receive_buffer_size,
253 sizeof(receive_buffer_size)) != 0) {
254 QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to set socket recv size";
255 return false;
256 }
257
258 // Send buffer size.
259 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &send_buffer_size,
260 sizeof(send_buffer_size)) != 0) {
261 QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to set socket send size";
262 return false;
263 }
264
265 if (GetQuicRestartFlag(quic_quiche_ecn_sockets)) {
266 QUIC_RESTART_FLAG_COUNT(quic_quiche_ecn_sockets);
267 unsigned int set = 1;
268 if (address_family == AF_INET &&
269 setsockopt(fd, IPPROTO_IP, IP_RECVTOS, &set, sizeof(set)) != 0) {
270 QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to request to receive ECN on "
271 << "socket";
272 return false;
273 }
274 if (address_family == AF_INET6 &&
275 setsockopt(fd, IPPROTO_IPV6, IPV6_RECVTCLASS, &set, sizeof(set)) != 0) {
276 QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to request to receive ECN on "
277 << "socket";
278 return false;
279 }
280 }
281
282 if (!(address_family == AF_INET6 && ipv6_only)) {
283 if (!EnableReceiveSelfIpAddressForV4(fd)) {
284 QUIC_LOG_FIRST_N(ERROR, 100)
285 << "Failed to enable receiving of self v4 ip";
286 return false;
287 }
288 }
289
290 if (address_family == AF_INET6) {
291 if (!EnableReceiveSelfIpAddressForV6(fd)) {
292 QUIC_LOG_FIRST_N(ERROR, 100)
293 << "Failed to enable receiving of self v6 ip";
294 return false;
295 }
296 }
297
298 return true;
299 }
300
Destroy(QuicUdpSocketFd fd)301 void QuicUdpSocketApi::Destroy(QuicUdpSocketFd fd) {
302 if (fd != kQuicInvalidSocketFd) {
303 absl::Status result = socket_api::Close(fd);
304 if (!result.ok()) {
305 QUIC_LOG_FIRST_N(WARNING, 100)
306 << "Failed to close UDP socket with error " << result;
307 }
308 }
309 }
310
Bind(QuicUdpSocketFd fd,QuicSocketAddress address)311 bool QuicUdpSocketApi::Bind(QuicUdpSocketFd fd, QuicSocketAddress address) {
312 sockaddr_storage addr = address.generic_address();
313 int addr_len =
314 address.host().IsIPv4() ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
315 return 0 == bind(fd, reinterpret_cast<sockaddr*>(&addr), addr_len);
316 }
317
BindInterface(QuicUdpSocketFd fd,const std::string & interface_name)318 bool QuicUdpSocketApi::BindInterface(QuicUdpSocketFd fd,
319 const std::string& interface_name) {
320 #if defined(__linux__) && !defined(__ANDROID_API__)
321 if (interface_name.empty() || interface_name.size() >= IFNAMSIZ) {
322 QUIC_BUG(udp_bad_interface_name)
323 << "interface_name must be nonempty and shorter than " << IFNAMSIZ;
324 return false;
325 }
326
327 return 0 == setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
328 interface_name.c_str(), interface_name.length());
329 #else
330 (void)fd;
331 (void)interface_name;
332 QUIC_BUG(interface_bind_not_implemented)
333 << "Interface binding is not implemented on this platform";
334 return false;
335 #endif
336 }
337
EnableDroppedPacketCount(QuicUdpSocketFd fd)338 bool QuicUdpSocketApi::EnableDroppedPacketCount(QuicUdpSocketFd fd) {
339 #if defined(__linux__) && defined(SO_RXQ_OVFL)
340 int get_overflow = 1;
341 return 0 == setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
342 sizeof(get_overflow));
343 #else
344 (void)fd;
345 return false;
346 #endif
347 }
348
EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd)349 bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd) {
350 int get_self_ip = 1;
351 return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_self_ip,
352 sizeof(get_self_ip));
353 }
354
EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd)355 bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd) {
356 int get_self_ip = 1;
357 return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_self_ip,
358 sizeof(get_self_ip));
359 }
360
EnableReceiveTimestamp(QuicUdpSocketFd fd)361 bool QuicUdpSocketApi::EnableReceiveTimestamp(QuicUdpSocketFd fd) {
362 #if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
363 int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
364 return 0 == setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, ×tamping,
365 sizeof(timestamping));
366 #else
367 (void)fd;
368 return false;
369 #endif
370 }
371
EnableReceiveTtlForV4(QuicUdpSocketFd fd)372 bool QuicUdpSocketApi::EnableReceiveTtlForV4(QuicUdpSocketFd fd) {
373 #if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
374 int get_ttl = 1;
375 return 0 == setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &get_ttl, sizeof(get_ttl));
376 #else
377 (void)fd;
378 return false;
379 #endif
380 }
381
EnableReceiveTtlForV6(QuicUdpSocketFd fd)382 bool QuicUdpSocketApi::EnableReceiveTtlForV6(QuicUdpSocketFd fd) {
383 #if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
384 int get_ttl = 1;
385 return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &get_ttl,
386 sizeof(get_ttl));
387 #else
388 (void)fd;
389 return false;
390 #endif
391 }
392
WaitUntilReadable(QuicUdpSocketFd fd,QuicTime::Delta timeout)393 bool QuicUdpSocketApi::WaitUntilReadable(QuicUdpSocketFd fd,
394 QuicTime::Delta timeout) {
395 fd_set read_fds;
396 FD_ZERO(&read_fds);
397 FD_SET(fd, &read_fds);
398
399 timeval select_timeout;
400 select_timeout.tv_sec = timeout.ToSeconds();
401 select_timeout.tv_usec = timeout.ToMicroseconds() % 1000000;
402
403 return 1 == select(1 + fd, &read_fds, nullptr, nullptr, &select_timeout);
404 }
405
ReadPacket(QuicUdpSocketFd fd,BitMask64 packet_info_interested,ReadPacketResult * result)406 void QuicUdpSocketApi::ReadPacket(QuicUdpSocketFd fd,
407 BitMask64 packet_info_interested,
408 ReadPacketResult* result) {
409 result->ok = false;
410 BufferSpan& packet_buffer = result->packet_buffer;
411 BufferSpan& control_buffer = result->control_buffer;
412 QuicUdpPacketInfo* packet_info = &result->packet_info;
413
414 QUICHE_DCHECK_GE(control_buffer.buffer_len, kMinCmsgSpaceForRead);
415
416 struct iovec iov = {packet_buffer.buffer, packet_buffer.buffer_len};
417 struct sockaddr_storage raw_peer_address;
418
419 if (control_buffer.buffer_len > 0) {
420 reinterpret_cast<struct cmsghdr*>(control_buffer.buffer)->cmsg_len =
421 control_buffer.buffer_len;
422 }
423
424 msghdr hdr;
425 hdr.msg_name = &raw_peer_address;
426 hdr.msg_namelen = sizeof(raw_peer_address);
427 hdr.msg_iov = &iov;
428 hdr.msg_iovlen = 1;
429 hdr.msg_flags = 0;
430 hdr.msg_control = control_buffer.buffer;
431 hdr.msg_controllen = control_buffer.buffer_len;
432
433 #if defined(__linux__)
434 // If MSG_TRUNC is set on Linux, recvmsg will return the real packet size even
435 // if |packet_buffer| is too small to receive it.
436 int flags = MSG_TRUNC;
437 #else
438 int flags = 0;
439 #endif
440
441 int bytes_read = recvmsg(fd, &hdr, flags);
442 if (bytes_read < 0) {
443 const int error_num = errno;
444 if (error_num != EAGAIN) {
445 QUIC_LOG_FIRST_N(ERROR, 100)
446 << "Error reading packet: " << strerror(error_num);
447 }
448 return;
449 }
450
451 if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) {
452 QUIC_BUG(quic_bug_10751_3)
453 << "Control buffer too small. size:" << control_buffer.buffer_len;
454 return;
455 }
456
457 if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC) ||
458 // Normally "bytes_read > packet_buffer.buffer_len" implies the MSG_TRUNC
459 // bit is set, but it is not the case if tested with config=android_arm64.
460 static_cast<size_t>(bytes_read) > packet_buffer.buffer_len) {
461 QUIC_LOG_FIRST_N(WARNING, 100)
462 << "Received truncated QUIC packet: buffer size:"
463 << packet_buffer.buffer_len << " packet size:" << bytes_read;
464 return;
465 }
466
467 packet_buffer.buffer_len = bytes_read;
468 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
469 packet_info->SetPeerAddress(QuicSocketAddress(raw_peer_address));
470 }
471
472 if (hdr.msg_controllen > 0) {
473 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
474 cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
475 BitMask64 prior_bitmask = packet_info->bitmask();
476 PopulatePacketInfoFromControlMessage(cmsg, packet_info,
477 packet_info_interested);
478 if (packet_info->bitmask() == prior_bitmask) {
479 QUIC_DLOG(INFO) << "Ignored cmsg_level:" << cmsg->cmsg_level
480 << ", cmsg_type:" << cmsg->cmsg_type;
481 }
482 }
483 }
484
485 result->ok = true;
486 }
487
ReadMultiplePackets(QuicUdpSocketFd fd,BitMask64 packet_info_interested,ReadPacketResults * results)488 size_t QuicUdpSocketApi::ReadMultiplePackets(QuicUdpSocketFd fd,
489 BitMask64 packet_info_interested,
490 ReadPacketResults* results) {
491 #if defined(__linux__) && !defined(__ANDROID__)
492 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::IS_GRO)) {
493 size_t num_packets = 0;
494 for (ReadPacketResult& result : *results) {
495 result.ok = false;
496 }
497 for (ReadPacketResult& result : *results) {
498 ReadPacket(fd, packet_info_interested, &result);
499 if (!result.ok) {
500 break;
501 }
502 ++num_packets;
503 }
504 return num_packets;
505 } else {
506 // Use recvmmsg.
507 size_t hdrs_size = sizeof(mmsghdr) * results->size();
508 mmsghdr* hdrs = static_cast<mmsghdr*>(alloca(hdrs_size));
509 memset(hdrs, 0, hdrs_size);
510
511 struct TempPerPacketData {
512 iovec iov;
513 sockaddr_storage raw_peer_address;
514 };
515 TempPerPacketData* packet_data_array = static_cast<TempPerPacketData*>(
516 alloca(sizeof(TempPerPacketData) * results->size()));
517
518 for (size_t i = 0; i < results->size(); ++i) {
519 (*results)[i].ok = false;
520
521 msghdr* hdr = &hdrs[i].msg_hdr;
522 TempPerPacketData* packet_data = &packet_data_array[i];
523 packet_data->iov.iov_base = (*results)[i].packet_buffer.buffer;
524 packet_data->iov.iov_len = (*results)[i].packet_buffer.buffer_len;
525
526 hdr->msg_name = &packet_data->raw_peer_address;
527 hdr->msg_namelen = sizeof(sockaddr_storage);
528 hdr->msg_iov = &packet_data->iov;
529 hdr->msg_iovlen = 1;
530 hdr->msg_flags = 0;
531 hdr->msg_control = (*results)[i].control_buffer.buffer;
532 hdr->msg_controllen = (*results)[i].control_buffer.buffer_len;
533
534 QUICHE_DCHECK_GE(hdr->msg_controllen, kMinCmsgSpaceForRead);
535 }
536 // If MSG_TRUNC is set on Linux, recvmmsg will return the real packet size
537 // in |hdrs[i].msg_len| even if packet buffer is too small to receive it.
538 int packets_read = recvmmsg(fd, hdrs, results->size(), MSG_TRUNC, nullptr);
539 if (packets_read <= 0) {
540 const int error_num = errno;
541 if (error_num != EAGAIN) {
542 QUIC_LOG_FIRST_N(ERROR, 100)
543 << "Error reading packets: " << strerror(error_num);
544 }
545 return 0;
546 }
547
548 for (int i = 0; i < packets_read; ++i) {
549 if (hdrs[i].msg_len == 0) {
550 continue;
551 }
552
553 msghdr& hdr = hdrs[i].msg_hdr;
554 if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) {
555 QUIC_BUG(quic_bug_10751_4) << "Control buffer too small. size:"
556 << (*results)[i].control_buffer.buffer_len
557 << ", need:" << hdr.msg_controllen;
558 continue;
559 }
560
561 if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC)) {
562 QUIC_LOG_FIRST_N(WARNING, 100)
563 << "Received truncated QUIC packet: buffer size:"
564 << (*results)[i].packet_buffer.buffer_len
565 << " packet size:" << hdrs[i].msg_len;
566 continue;
567 }
568
569 (*results)[i].ok = true;
570 (*results)[i].packet_buffer.buffer_len = hdrs[i].msg_len;
571
572 QuicUdpPacketInfo* packet_info = &(*results)[i].packet_info;
573 if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
574 packet_info->SetPeerAddress(
575 QuicSocketAddress(packet_data_array[i].raw_peer_address));
576 }
577
578 if (hdr.msg_controllen > 0) {
579 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
580 cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
581 PopulatePacketInfoFromControlMessage(cmsg, packet_info,
582 packet_info_interested);
583 }
584 }
585 }
586 return packets_read;
587 }
588 #else
589 size_t num_packets = 0;
590 for (ReadPacketResult& result : *results) {
591 result.ok = false;
592 }
593 for (ReadPacketResult& result : *results) {
594 errno = 0;
595 ReadPacket(fd, packet_info_interested, &result);
596 if (!result.ok && errno == EAGAIN) {
597 break;
598 }
599 ++num_packets;
600 }
601 return num_packets;
602 #endif
603 }
604
WritePacket(QuicUdpSocketFd fd,const char * packet_buffer,size_t packet_buffer_len,const QuicUdpPacketInfo & packet_info)605 WriteResult QuicUdpSocketApi::WritePacket(
606 QuicUdpSocketFd fd, const char* packet_buffer, size_t packet_buffer_len,
607 const QuicUdpPacketInfo& packet_info) {
608 if (!packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
609 return WriteResult(WRITE_STATUS_ERROR, EINVAL);
610 }
611
612 char control_buffer[512];
613 sockaddr_storage raw_peer_address =
614 packet_info.peer_address().generic_address();
615 iovec iov = {const_cast<char*>(packet_buffer), packet_buffer_len};
616
617 msghdr hdr;
618 hdr.msg_name = &raw_peer_address;
619 hdr.msg_namelen = packet_info.peer_address().host().IsIPv4()
620 ? sizeof(sockaddr_in)
621 : sizeof(sockaddr_in6);
622 hdr.msg_iov = &iov;
623 hdr.msg_iovlen = 1;
624 hdr.msg_flags = 0;
625 hdr.msg_control = nullptr;
626 hdr.msg_controllen = 0;
627
628 cmsghdr* cmsg = nullptr;
629
630 // Set self IP.
631 if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP) &&
632 packet_info.self_v4_ip().IsInitialized()) {
633 if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IP,
634 IP_PKTINFO, sizeof(in_pktinfo), &cmsg)) {
635 QUIC_LOG_FIRST_N(ERROR, 100)
636 << "Not enough buffer to set self v4 ip address.";
637 return WriteResult(WRITE_STATUS_ERROR, EINVAL);
638 }
639 SetV4SelfIpInControlMessage(packet_info.self_v4_ip(), cmsg);
640 } else if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP) &&
641 packet_info.self_v6_ip().IsInitialized()) {
642 if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IPV6,
643 IPV6_PKTINFO, sizeof(in6_pktinfo), &cmsg)) {
644 QUIC_LOG_FIRST_N(ERROR, 100)
645 << "Not enough buffer to set self v6 ip address.";
646 return WriteResult(WRITE_STATUS_ERROR, EINVAL);
647 }
648 SetV6SelfIpInControlMessage(packet_info.self_v6_ip(), cmsg);
649 }
650
651 #if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
652 // Set ttl.
653 if (packet_info.HasValue(QuicUdpPacketInfoBit::TTL)) {
654 int cmsg_level =
655 packet_info.peer_address().host().IsIPv4() ? IPPROTO_IP : IPPROTO_IPV6;
656 int cmsg_type =
657 packet_info.peer_address().host().IsIPv4() ? IP_TTL : IPV6_HOPLIMIT;
658 if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), cmsg_level,
659 cmsg_type, sizeof(int), &cmsg)) {
660 QUIC_LOG_FIRST_N(ERROR, 100) << "Not enough buffer to set ttl.";
661 return WriteResult(WRITE_STATUS_ERROR, EINVAL);
662 }
663 *reinterpret_cast<int*>(CMSG_DATA(cmsg)) = packet_info.ttl();
664 }
665 #endif
666
667 // TODO(b/270584616): This code block might go away when full support for
668 // marking ECN is implemented.
669 if (packet_info.HasValue(QuicUdpPacketInfoBit::ECN)) {
670 int cmsg_level =
671 packet_info.peer_address().host().IsIPv4() ? IPPROTO_IP : IPPROTO_IPV6;
672 int cmsg_type;
673 unsigned char value_buf[20];
674 socklen_t value_len = sizeof(value_buf);
675 if (GetQuicRestartFlag(quic_platform_tos_sockopt)) {
676 QUIC_RESTART_FLAG_COUNT(quic_platform_tos_sockopt);
677 if (GetEcnCmsgArgsPreserveDscp(
678 fd, packet_info.peer_address().host().address_family(),
679 packet_info.ecn_codepoint(), cmsg_type, value_buf,
680 value_len) != 0) {
681 QUIC_LOG_FIRST_N(ERROR, 100)
682 << "Could not get ECN msg type for this platform.";
683 return WriteResult(WRITE_STATUS_ERROR, EINVAL);
684 }
685 } else {
686 cmsg_type = (cmsg_level == IPPROTO_IP) ? IP_TOS : IPV6_TCLASS;
687 *(int*)value_buf = static_cast<int>(packet_info.ecn_codepoint());
688 value_len = sizeof(int);
689 }
690 if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), cmsg_level,
691 cmsg_type, value_len, &cmsg)) {
692 QUIC_LOG_FIRST_N(ERROR, 100) << "Not enough buffer to set ECN.";
693 return WriteResult(WRITE_STATUS_ERROR, EINVAL);
694 }
695 memcpy(CMSG_DATA(cmsg), value_buf, value_len);
696 }
697
698 int rc;
699 do {
700 rc = sendmsg(fd, &hdr, 0);
701 } while (rc < 0 && errno == EINTR);
702 if (rc >= 0) {
703 return WriteResult(WRITE_STATUS_OK, rc);
704 }
705 return WriteResult((errno == EAGAIN || errno == EWOULDBLOCK)
706 ? WRITE_STATUS_BLOCKED
707 : WRITE_STATUS_ERROR,
708 errno);
709 }
710
711 } // namespace quic
712