• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &timestamping,
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