• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "build/build_config.h"
11 
12 #if BUILDFLAG(IS_APPLE)
13 // This must be defined before including <netinet/in.h>
14 // to use IPV6_DONTFRAG, one of the IPv6 Sockets option introduced by RFC 3542
15 #define __APPLE_USE_RFC_3542
16 #endif  // BUILDFLAG(IS_APPLE)
17 
18 #include "net/socket/udp_socket_posix.h"
19 
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <net/if.h>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #include <sys/ioctl.h>
26 #include <sys/socket.h>
27 
28 #include <memory>
29 
30 #include "base/debug/alias.h"
31 #include "base/files/file_util.h"
32 #include "base/functional/bind.h"
33 #include "base/functional/callback.h"
34 #include "base/functional/callback_helpers.h"
35 #include "base/logging.h"
36 #include "base/posix/eintr_wrapper.h"
37 #include "base/rand_util.h"
38 #include "base/task/current_thread.h"
39 #include "base/task/thread_pool.h"
40 #include "build/chromeos_buildflags.h"
41 #include "net/base/cronet_buildflags.h"
42 #include "net/base/io_buffer.h"
43 #include "net/base/ip_address.h"
44 #include "net/base/ip_endpoint.h"
45 #include "net/base/net_errors.h"
46 #include "net/base/network_activity_monitor.h"
47 #include "net/base/sockaddr_storage.h"
48 #include "net/base/trace_constants.h"
49 #include "net/base/tracing.h"
50 #include "net/log/net_log.h"
51 #include "net/log/net_log_event_type.h"
52 #include "net/log/net_log_source.h"
53 #include "net/log/net_log_source_type.h"
54 #include "net/socket/socket_descriptor.h"
55 #include "net/socket/socket_options.h"
56 #include "net/socket/socket_tag.h"
57 #include "net/socket/udp_net_log_parameters.h"
58 #include "net/traffic_annotation/network_traffic_annotation.h"
59 
60 #if BUILDFLAG(IS_ANDROID)
61 #include "base/native_library.h"
62 #include "net/android/network_library.h"
63 #endif  // BUILDFLAG(IS_ANDROID)
64 
65 #if BUILDFLAG(IS_APPLE)
66 #include "net/base/apple/guarded_fd.h"
67 #endif  // BUILDFLAG(IS_APPLE)
68 
69 #if BUILDFLAG(IS_MAC)
70 #include "base/mac/mac_util.h"
71 #endif  // BUILDFLAG(IS_MAC)
72 
73 namespace net {
74 
75 namespace {
76 
77 constexpr int kBindRetries = 10;
78 constexpr int kPortStart = 1024;
79 constexpr int kPortEnd = 65535;
80 
GetSocketFDHash(int fd)81 int GetSocketFDHash(int fd) {
82   return fd ^ 1595649551;
83 }
84 
85 }  // namespace
86 
UDPSocketPosix(DatagramSocket::BindType bind_type,net::NetLog * net_log,const net::NetLogSource & source)87 UDPSocketPosix::UDPSocketPosix(DatagramSocket::BindType bind_type,
88                                net::NetLog* net_log,
89                                const net::NetLogSource& source)
90     : socket_(kInvalidSocket),
91       bind_type_(bind_type),
92       read_socket_watcher_(FROM_HERE),
93       write_socket_watcher_(FROM_HERE),
94       read_watcher_(this),
95       write_watcher_(this),
96       net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)),
97       bound_network_(handles::kInvalidNetworkHandle) {
98   net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source);
99 }
100 
UDPSocketPosix(DatagramSocket::BindType bind_type,NetLogWithSource source_net_log)101 UDPSocketPosix::UDPSocketPosix(DatagramSocket::BindType bind_type,
102                                NetLogWithSource source_net_log)
103     : socket_(kInvalidSocket),
104       bind_type_(bind_type),
105       read_socket_watcher_(FROM_HERE),
106       write_socket_watcher_(FROM_HERE),
107       read_watcher_(this),
108       write_watcher_(this),
109       net_log_(source_net_log),
110       bound_network_(handles::kInvalidNetworkHandle) {
111   net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE,
112                                        net_log_.source());
113 }
114 
~UDPSocketPosix()115 UDPSocketPosix::~UDPSocketPosix() {
116   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
117   Close();
118   net_log_.EndEvent(NetLogEventType::SOCKET_ALIVE);
119 }
120 
Open(AddressFamily address_family)121 int UDPSocketPosix::Open(AddressFamily address_family) {
122   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
123   DCHECK_EQ(socket_, kInvalidSocket);
124 
125   auto owned_socket_count = TryAcquireGlobalUDPSocketCount();
126   if (owned_socket_count.empty())
127     return ERR_INSUFFICIENT_RESOURCES;
128 
129   owned_socket_count_ = std::move(owned_socket_count);
130   addr_family_ = ConvertAddressFamily(address_family);
131   socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
132   if (socket_ == kInvalidSocket) {
133     owned_socket_count_.Reset();
134     return MapSystemError(errno);
135   }
136 
137   return ConfigureOpenedSocket();
138 }
139 
AdoptOpenedSocket(AddressFamily address_family,int socket)140 int UDPSocketPosix::AdoptOpenedSocket(AddressFamily address_family,
141                                       int socket) {
142   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
143   DCHECK_EQ(socket_, kInvalidSocket);
144   auto owned_socket_count = TryAcquireGlobalUDPSocketCount();
145   if (owned_socket_count.empty()) {
146     return ERR_INSUFFICIENT_RESOURCES;
147   }
148 
149   owned_socket_count_ = std::move(owned_socket_count);
150   socket_ = socket;
151   addr_family_ = ConvertAddressFamily(address_family);
152   return ConfigureOpenedSocket();
153 }
154 
ConfigureOpenedSocket()155 int UDPSocketPosix::ConfigureOpenedSocket() {
156 #if BUILDFLAG(IS_APPLE) && !BUILDFLAG(CRONET_BUILD)
157   // https://crbug.com/41271555: Guard against a file descriptor being closed
158   // out from underneath the socket.
159   guardid_t guardid = reinterpret_cast<guardid_t>(this);
160   PCHECK(change_fdguard_np(socket_, nullptr, 0, &guardid,
161                            GUARD_CLOSE | GUARD_DUP, nullptr) == 0);
162 #endif  // BUILDFLAG(IS_APPLE) && !BUILDFLAG(CRONET_BUILD)
163   socket_hash_ = GetSocketFDHash(socket_);
164   if (!base::SetNonBlocking(socket_)) {
165     const int err = MapSystemError(errno);
166     Close();
167     return err;
168   }
169   if (tag_ != SocketTag())
170     tag_.Apply(socket_);
171 
172   return OK;
173 }
174 
Close()175 void UDPSocketPosix::Close() {
176   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
177 
178   owned_socket_count_.Reset();
179 
180   if (socket_ == kInvalidSocket)
181     return;
182 
183   // Zero out any pending read/write callback state.
184   read_buf_.reset();
185   read_buf_len_ = 0;
186   read_callback_.Reset();
187   recv_from_address_ = nullptr;
188   write_buf_.reset();
189   write_buf_len_ = 0;
190   write_callback_.Reset();
191   send_to_address_.reset();
192 
193   bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
194   DCHECK(ok);
195   ok = write_socket_watcher_.StopWatchingFileDescriptor();
196   DCHECK(ok);
197 
198   // Verify that |socket_| hasn't been corrupted. Needed to debug
199   // https://crbug.com/41426706.
200   CHECK_EQ(socket_hash_, GetSocketFDHash(socket_));
201   TRACE_EVENT("base", perfetto::StaticString{"CloseSocketUDP"});
202 
203 #if BUILDFLAG(IS_APPLE) && !BUILDFLAG(CRONET_BUILD)
204   // Attempt to clear errors on the socket so that they are not returned by
205   // close(). This seems to be effective at clearing some, but not all,
206   // EPROTOTYPE errors. See https://crbug.com/40732798.
207   int value = 0;
208   socklen_t value_len = sizeof(value);
209   HANDLE_EINTR(getsockopt(socket_, SOL_SOCKET, SO_ERROR, &value, &value_len));
210 
211   // https://crbug.com/41271555: Guard against a file descriptor being closed
212   // out from underneath the socket.
213   guardid_t guardid = reinterpret_cast<guardid_t>(this);
214   if (IGNORE_EINTR(guarded_close_np(socket_, &guardid)) != 0) {
215     // There is a bug in the Mac OS kernel that it can return an ENOTCONN or
216     // EPROTOTYPE error. In this case we don't know whether the file descriptor
217     // is still allocated or not. We cannot safely close the file descriptor
218     // because it may have been reused by another thread in the meantime. We may
219     // leak file handles here and cause a crash indirectly later. See
220     // https://crbug.com/40732798.
221     PCHECK(errno == ENOTCONN || errno == EPROTOTYPE);
222   }
223 #else
224   PCHECK(IGNORE_EINTR(close(socket_)) == 0);
225 #endif  // BUILDFLAG(IS_APPLE) && !BUILDFLAG(CRONET_BUILD)
226 
227   socket_ = kInvalidSocket;
228   addr_family_ = 0;
229   is_connected_ = false;
230   tag_ = SocketTag();
231 }
232 
GetPeerAddress(IPEndPoint * address) const233 int UDPSocketPosix::GetPeerAddress(IPEndPoint* address) const {
234   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
235   DCHECK(address);
236   if (!is_connected())
237     return ERR_SOCKET_NOT_CONNECTED;
238 
239   if (!remote_address_.get()) {
240     SockaddrStorage storage;
241     if (getpeername(socket_, storage.addr, &storage.addr_len))
242       return MapSystemError(errno);
243     auto endpoint = std::make_unique<IPEndPoint>();
244     if (!endpoint->FromSockAddr(storage.addr, storage.addr_len))
245       return ERR_ADDRESS_INVALID;
246     remote_address_ = std::move(endpoint);
247   }
248 
249   *address = *remote_address_;
250   return OK;
251 }
252 
GetLocalAddress(IPEndPoint * address) const253 int UDPSocketPosix::GetLocalAddress(IPEndPoint* address) const {
254   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
255   DCHECK(address);
256   if (!is_connected())
257     return ERR_SOCKET_NOT_CONNECTED;
258 
259   if (!local_address_.get()) {
260     SockaddrStorage storage;
261     if (getsockname(socket_, storage.addr, &storage.addr_len))
262       return MapSystemError(errno);
263     auto endpoint = std::make_unique<IPEndPoint>();
264     if (!endpoint->FromSockAddr(storage.addr, storage.addr_len))
265       return ERR_ADDRESS_INVALID;
266     local_address_ = std::move(endpoint);
267     net_log_.AddEvent(NetLogEventType::UDP_LOCAL_ADDRESS, [&] {
268       return CreateNetLogUDPConnectParams(*local_address_, bound_network_);
269     });
270   }
271 
272   *address = *local_address_;
273   return OK;
274 }
275 
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)276 int UDPSocketPosix::Read(IOBuffer* buf,
277                          int buf_len,
278                          CompletionOnceCallback callback) {
279   return RecvFrom(buf, buf_len, nullptr, std::move(callback));
280 }
281 
RecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address,CompletionOnceCallback callback)282 int UDPSocketPosix::RecvFrom(IOBuffer* buf,
283                              int buf_len,
284                              IPEndPoint* address,
285                              CompletionOnceCallback callback) {
286   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
287   DCHECK_NE(kInvalidSocket, socket_);
288   CHECK(read_callback_.is_null());
289   DCHECK(!recv_from_address_);
290   DCHECK(!callback.is_null());  // Synchronous operation not supported
291   DCHECK_GT(buf_len, 0);
292 
293   int nread = InternalRecvFrom(buf, buf_len, address);
294   if (nread != ERR_IO_PENDING)
295     return nread;
296 
297   if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
298           socket_, true, base::MessagePumpForIO::WATCH_READ,
299           &read_socket_watcher_, &read_watcher_)) {
300     PLOG(ERROR) << "WatchFileDescriptor failed on read";
301     int result = MapSystemError(errno);
302     LogRead(result, nullptr, 0, nullptr);
303     return result;
304   }
305 
306   read_buf_ = buf;
307   read_buf_len_ = buf_len;
308   recv_from_address_ = address;
309   read_callback_ = std::move(callback);
310   return ERR_IO_PENDING;
311 }
312 
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)313 int UDPSocketPosix::Write(
314     IOBuffer* buf,
315     int buf_len,
316     CompletionOnceCallback callback,
317     const NetworkTrafficAnnotationTag& traffic_annotation) {
318   return SendToOrWrite(buf, buf_len, nullptr, std::move(callback));
319 }
320 
SendTo(IOBuffer * buf,int buf_len,const IPEndPoint & address,CompletionOnceCallback callback)321 int UDPSocketPosix::SendTo(IOBuffer* buf,
322                            int buf_len,
323                            const IPEndPoint& address,
324                            CompletionOnceCallback callback) {
325   return SendToOrWrite(buf, buf_len, &address, std::move(callback));
326 }
327 
SendToOrWrite(IOBuffer * buf,int buf_len,const IPEndPoint * address,CompletionOnceCallback callback)328 int UDPSocketPosix::SendToOrWrite(IOBuffer* buf,
329                                   int buf_len,
330                                   const IPEndPoint* address,
331                                   CompletionOnceCallback callback) {
332   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
333   DCHECK_NE(kInvalidSocket, socket_);
334   CHECK(write_callback_.is_null());
335   DCHECK(!callback.is_null());  // Synchronous operation not supported
336   DCHECK_GT(buf_len, 0);
337 
338   if (int result = InternalSendTo(buf, buf_len, address);
339       result != ERR_IO_PENDING) {
340     return result;
341   }
342 
343   if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
344           socket_, true, base::MessagePumpForIO::WATCH_WRITE,
345           &write_socket_watcher_, &write_watcher_)) {
346     DVPLOG(1) << "WatchFileDescriptor failed on write";
347     int result = MapSystemError(errno);
348     LogWrite(result, nullptr, nullptr);
349     return result;
350   }
351 
352   write_buf_ = buf;
353   write_buf_len_ = buf_len;
354   DCHECK(!send_to_address_.get());
355   if (address) {
356     send_to_address_ = std::make_unique<IPEndPoint>(*address);
357   }
358   write_callback_ = std::move(callback);
359   return ERR_IO_PENDING;
360 }
361 
Connect(const IPEndPoint & address)362 int UDPSocketPosix::Connect(const IPEndPoint& address) {
363   DCHECK_NE(socket_, kInvalidSocket);
364   net_log_.BeginEvent(NetLogEventType::UDP_CONNECT, [&] {
365     return CreateNetLogUDPConnectParams(address, bound_network_);
366   });
367   int rv = SetMulticastOptions();
368   if (rv != OK)
369     return rv;
370   rv = InternalConnect(address);
371   net_log_.EndEventWithNetErrorCode(NetLogEventType::UDP_CONNECT, rv);
372   is_connected_ = (rv == OK);
373   if (rv != OK)
374     tag_ = SocketTag();
375   return rv;
376 }
377 
InternalConnect(const IPEndPoint & address)378 int UDPSocketPosix::InternalConnect(const IPEndPoint& address) {
379   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
380   DCHECK(!is_connected());
381   DCHECK(!remote_address_.get());
382 
383   int rv = 0;
384   if (bind_type_ == DatagramSocket::RANDOM_BIND) {
385     // Construct IPAddress of appropriate size (IPv4 or IPv6) of 0s,
386     // representing INADDR_ANY or in6addr_any.
387     size_t addr_size = address.GetSockAddrFamily() == AF_INET
388                            ? IPAddress::kIPv4AddressSize
389                            : IPAddress::kIPv6AddressSize;
390     rv = RandomBind(IPAddress::AllZeros(addr_size));
391   }
392   // else connect() does the DatagramSocket::DEFAULT_BIND
393 
394   if (rv < 0) {
395     return rv;
396   }
397 
398   SockaddrStorage storage;
399   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
400     return ERR_ADDRESS_INVALID;
401 
402   rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len));
403   if (rv < 0)
404     return MapSystemError(errno);
405 
406   remote_address_ = std::make_unique<IPEndPoint>(address);
407   return rv;
408 }
409 
Bind(const IPEndPoint & address)410 int UDPSocketPosix::Bind(const IPEndPoint& address) {
411   DCHECK_NE(socket_, kInvalidSocket);
412   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
413   DCHECK(!is_connected());
414 
415   int rv = SetMulticastOptions();
416   if (rv < 0)
417     return rv;
418 
419   rv = DoBind(address);
420   if (rv < 0)
421     return rv;
422 
423   is_connected_ = true;
424   local_address_.reset();
425   return rv;
426 }
427 
BindToNetwork(handles::NetworkHandle network)428 int UDPSocketPosix::BindToNetwork(handles::NetworkHandle network) {
429   DCHECK_NE(socket_, kInvalidSocket);
430   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
431   DCHECK(!is_connected());
432 #if BUILDFLAG(IS_ANDROID)
433   int rv = net::android::BindToNetwork(socket_, network);
434   if (rv == OK)
435     bound_network_ = network;
436   return rv;
437 #else
438   NOTIMPLEMENTED();
439   return ERR_NOT_IMPLEMENTED;
440 #endif
441 }
442 
SetReceiveBufferSize(int32_t size)443 int UDPSocketPosix::SetReceiveBufferSize(int32_t size) {
444   DCHECK_NE(socket_, kInvalidSocket);
445   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
446   return SetSocketReceiveBufferSize(socket_, size);
447 }
448 
SetSendBufferSize(int32_t size)449 int UDPSocketPosix::SetSendBufferSize(int32_t size) {
450   DCHECK_NE(socket_, kInvalidSocket);
451   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
452   return SetSocketSendBufferSize(socket_, size);
453 }
454 
SetDoNotFragment()455 int UDPSocketPosix::SetDoNotFragment() {
456   DCHECK_NE(socket_, kInvalidSocket);
457   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
458 
459 #if !defined(IP_PMTUDISC_DO) && !BUILDFLAG(IS_MAC)
460   return ERR_NOT_IMPLEMENTED;
461 
462 #elif BUILDFLAG(IS_MAC)
463   int val = 1;
464   if (addr_family_ == AF_INET6) {
465     int rv =
466         setsockopt(socket_, IPPROTO_IPV6, IPV6_DONTFRAG, &val, sizeof(val));
467     // IP_DONTFRAG is not supported on v4mapped addresses.
468     return rv == 0 ? OK : MapSystemError(errno);
469   }
470   int rv = setsockopt(socket_, IPPROTO_IP, IP_DONTFRAG, &val, sizeof(val));
471   return rv == 0 ? OK : MapSystemError(errno);
472 
473 #else
474   if (addr_family_ == AF_INET6) {
475     int val = IPV6_PMTUDISC_DO;
476     if (setsockopt(socket_, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val,
477                    sizeof(val)) != 0) {
478       return MapSystemError(errno);
479     }
480 
481     int v6_only = false;
482     socklen_t v6_only_len = sizeof(v6_only);
483     if (getsockopt(socket_, IPPROTO_IPV6, IPV6_V6ONLY, &v6_only,
484                    &v6_only_len) != 0) {
485       return MapSystemError(errno);
486     }
487 
488     if (v6_only)
489       return OK;
490   }
491 
492   int val = IP_PMTUDISC_DO;
493   int rv = setsockopt(socket_, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));
494   return rv == 0 ? OK : MapSystemError(errno);
495 #endif
496 }
497 
SetRecvTos()498 int UDPSocketPosix::SetRecvTos() {
499   DCHECK_NE(socket_, kInvalidSocket);
500   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
501 
502   unsigned int ecn = 1;
503   if (addr_family_ == AF_INET6) {
504     if (setsockopt(socket_, IPPROTO_IPV6, IPV6_RECVTCLASS, &ecn, sizeof(ecn)) !=
505         0) {
506       return MapSystemError(errno);
507     }
508 #if BUILDFLAG(IS_APPLE)
509     // Linux requires dual-stack sockets to have the sockopt set on both levels.
510     // Apple does not, and in fact returns an error if it is.
511     return OK;
512 #else
513     int v6_only = false;
514     socklen_t v6_only_len = sizeof(v6_only);
515     if (getsockopt(socket_, IPPROTO_IPV6, IPV6_V6ONLY, &v6_only,
516                    &v6_only_len) != 0) {
517       return MapSystemError(errno);
518     }
519     if (v6_only) {
520       return OK;
521     }
522 #endif  // BUILDFLAG(IS_APPLE)
523   }
524 
525   int rv = setsockopt(socket_, IPPROTO_IP, IP_RECVTOS, &ecn, sizeof(ecn));
526   return rv == 0 ? OK : MapSystemError(errno);
527 }
528 
SetMsgConfirm(bool confirm)529 void UDPSocketPosix::SetMsgConfirm(bool confirm) {
530 #if !BUILDFLAG(IS_APPLE)
531   if (confirm) {
532     sendto_flags_ |= MSG_CONFIRM;
533   } else {
534     sendto_flags_ &= ~MSG_CONFIRM;
535   }
536 #endif  // !BUILDFLAG(IS_APPLE)
537 }
538 
AllowAddressReuse()539 int UDPSocketPosix::AllowAddressReuse() {
540   DCHECK_NE(socket_, kInvalidSocket);
541   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
542   DCHECK(!is_connected());
543   return SetReuseAddr(socket_, true);
544 }
545 
SetBroadcast(bool broadcast)546 int UDPSocketPosix::SetBroadcast(bool broadcast) {
547   DCHECK_NE(socket_, kInvalidSocket);
548   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
549   int value = broadcast ? 1 : 0;
550   int rv;
551 #if BUILDFLAG(IS_APPLE)
552   // SO_REUSEPORT on OSX permits multiple processes to each receive
553   // UDP multicast or broadcast datagrams destined for the bound
554   // port.
555   // This is only being set on OSX because its behavior is platform dependent
556   // and we are playing it safe by only setting it on platforms where things
557   // break.
558   rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value));
559   if (rv != 0)
560     return MapSystemError(errno);
561 #endif  // BUILDFLAG(IS_APPLE)
562   rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
563 
564   return rv == 0 ? OK : MapSystemError(errno);
565 }
566 
AllowAddressSharingForMulticast()567 int UDPSocketPosix::AllowAddressSharingForMulticast() {
568   DCHECK_NE(socket_, kInvalidSocket);
569   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
570   DCHECK(!is_connected());
571 
572   int rv = AllowAddressReuse();
573   if (rv != OK)
574     return rv;
575 
576 #ifdef SO_REUSEPORT
577   // Attempt to set SO_REUSEPORT if available. On some platforms, this is
578   // necessary to allow the address to be fully shared between separate sockets.
579   // On platforms where the option does not exist, SO_REUSEADDR should be
580   // sufficient to share multicast packets if such sharing is at all possible.
581   int value = 1;
582   rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value));
583   // Ignore errors that the option does not exist.
584   if (rv != 0 && errno != ENOPROTOOPT)
585     return MapSystemError(errno);
586 #endif  // SO_REUSEPORT
587 
588   return OK;
589 }
590 
OnFileCanReadWithoutBlocking(int)591 void UDPSocketPosix::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
592   TRACE_EVENT(NetTracingCategory(),
593               "UDPSocketPosix::ReadWatcher::OnFileCanReadWithoutBlocking");
594   if (!socket_->read_callback_.is_null())
595     socket_->DidCompleteRead();
596 }
597 
OnFileCanWriteWithoutBlocking(int)598 void UDPSocketPosix::WriteWatcher::OnFileCanWriteWithoutBlocking(int) {
599   if (!socket_->write_callback_.is_null())
600     socket_->DidCompleteWrite();
601 }
602 
DoReadCallback(int rv)603 void UDPSocketPosix::DoReadCallback(int rv) {
604   DCHECK_NE(rv, ERR_IO_PENDING);
605   DCHECK(!read_callback_.is_null());
606 
607   // Since Run() may result in Read() being called,
608   // clear |read_callback_| up front.
609   std::move(read_callback_).Run(rv);
610 }
611 
DoWriteCallback(int rv)612 void UDPSocketPosix::DoWriteCallback(int rv) {
613   DCHECK_NE(rv, ERR_IO_PENDING);
614   DCHECK(!write_callback_.is_null());
615 
616   // Since Run() may result in Write() being called,
617   // clear |write_callback_| up front.
618   std::move(write_callback_).Run(rv);
619 }
620 
DidCompleteRead()621 void UDPSocketPosix::DidCompleteRead() {
622   int result =
623       InternalRecvFrom(read_buf_.get(), read_buf_len_, recv_from_address_);
624   if (result != ERR_IO_PENDING) {
625     read_buf_.reset();
626     read_buf_len_ = 0;
627     recv_from_address_ = nullptr;
628     bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
629     DCHECK(ok);
630     DoReadCallback(result);
631   }
632 }
633 
LogRead(int result,const char * bytes,socklen_t addr_len,const sockaddr * addr)634 void UDPSocketPosix::LogRead(int result,
635                              const char* bytes,
636                              socklen_t addr_len,
637                              const sockaddr* addr) {
638   if (result < 0) {
639     net_log_.AddEventWithNetErrorCode(NetLogEventType::UDP_RECEIVE_ERROR,
640                                       result);
641     return;
642   }
643 
644   if (net_log_.IsCapturing()) {
645     DCHECK(addr_len > 0);
646     DCHECK(addr);
647 
648     IPEndPoint address;
649     bool is_address_valid = address.FromSockAddr(addr, addr_len);
650     NetLogUDPDataTransfer(net_log_, NetLogEventType::UDP_BYTES_RECEIVED, result,
651                           bytes, is_address_valid ? &address : nullptr);
652   }
653 
654   activity_monitor::IncrementBytesReceived(result);
655 }
656 
DidCompleteWrite()657 void UDPSocketPosix::DidCompleteWrite() {
658   int result =
659       InternalSendTo(write_buf_.get(), write_buf_len_, send_to_address_.get());
660 
661   if (result != ERR_IO_PENDING) {
662     write_buf_.reset();
663     write_buf_len_ = 0;
664     send_to_address_.reset();
665     write_socket_watcher_.StopWatchingFileDescriptor();
666     DoWriteCallback(result);
667   }
668 }
669 
LogWrite(int result,const char * bytes,const IPEndPoint * address)670 void UDPSocketPosix::LogWrite(int result,
671                               const char* bytes,
672                               const IPEndPoint* address) {
673   if (result < 0) {
674     net_log_.AddEventWithNetErrorCode(NetLogEventType::UDP_SEND_ERROR, result);
675     return;
676   }
677 
678   if (net_log_.IsCapturing()) {
679     NetLogUDPDataTransfer(net_log_, NetLogEventType::UDP_BYTES_SENT, result,
680                           bytes, address);
681   }
682 }
683 
684 // TODO(crbug.com/40285166): Because InternalRecvFromConnectedSocket() uses
685 // recvfrom() instead of recvmsg(), it cannot report received ECN marks for
686 // QUIC ACK-ECN frames. It might be time to deprecate
687 // experimental_recv_optimization_enabled_ if that experiment has run its
688 // course.
InternalRecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address)689 int UDPSocketPosix::InternalRecvFrom(IOBuffer* buf,
690                                      int buf_len,
691                                      IPEndPoint* address) {
692   // If the socket is connected and the remote address is known
693   // use the more efficient method that uses read() instead of recvmsg().
694   if (experimental_recv_optimization_enabled_ && is_connected_ &&
695       remote_address_) {
696     return InternalRecvFromConnectedSocket(buf, buf_len, address);
697   }
698   return InternalRecvFromNonConnectedSocket(buf, buf_len, address);
699 }
700 
InternalRecvFromConnectedSocket(IOBuffer * buf,int buf_len,IPEndPoint * address)701 int UDPSocketPosix::InternalRecvFromConnectedSocket(IOBuffer* buf,
702                                                     int buf_len,
703                                                     IPEndPoint* address) {
704   DCHECK(is_connected_);
705   DCHECK(remote_address_);
706   int result;
707   int bytes_transferred = HANDLE_EINTR(read(socket_, buf->data(), buf_len));
708   if (bytes_transferred < 0) {
709     result = MapSystemError(errno);
710     if (result == ERR_IO_PENDING) {
711       return result;
712     }
713   } else if (bytes_transferred == buf_len) {
714     // NB: recv(..., MSG_TRUNC) would be a more reliable way to do this on
715     // Linux, but isn't supported by POSIX.
716     result = ERR_MSG_TOO_BIG;
717   } else {
718     result = bytes_transferred;
719     if (address) {
720       *address = *remote_address_.get();
721     }
722   }
723 
724   SockaddrStorage sock_addr;
725   bool success =
726         remote_address_->ToSockAddr(sock_addr.addr, &sock_addr.addr_len);
727     DCHECK(success);
728     LogRead(result, buf->data(), sock_addr.addr_len, sock_addr.addr);
729   return result;
730 }
731 
InternalRecvFromNonConnectedSocket(IOBuffer * buf,int buf_len,IPEndPoint * address)732 int UDPSocketPosix::InternalRecvFromNonConnectedSocket(IOBuffer* buf,
733                                                        int buf_len,
734                                                        IPEndPoint* address) {
735   SockaddrStorage storage;
736   struct iovec iov = {
737       .iov_base = buf->data(),
738       .iov_len = static_cast<size_t>(buf_len),
739   };
740   // control_buffer needs to be big enough to accommodate the maximum
741   // conceivable number of CMSGs. Other (proprietary) Google QUIC code uses
742   // 512 Bytes, re-used here.
743   char control_buffer[512];
744   struct msghdr msg = {
745       .msg_name = storage.addr,
746       .msg_namelen = storage.addr_len,
747       .msg_iov = &iov,
748       .msg_iovlen = 1,
749       .msg_control = control_buffer,
750       .msg_controllen = ABSL_ARRAYSIZE(control_buffer),
751   };
752   int result;
753   int bytes_transferred = HANDLE_EINTR(recvmsg(socket_, &msg, 0));
754   if (bytes_transferred < 0) {
755     result = MapSystemError(errno);
756     if (result == ERR_IO_PENDING) {
757       return result;
758     }
759   } else {
760     storage.addr_len = msg.msg_namelen;
761     if (msg.msg_flags & MSG_TRUNC) {
762       // NB: recvfrom(..., MSG_TRUNC, ...) would be a simpler way to do this on
763       // Linux, but isn't supported by POSIX.
764       result = ERR_MSG_TOO_BIG;
765     } else if (address &&
766                !address->FromSockAddr(storage.addr, storage.addr_len)) {
767       result = ERR_ADDRESS_INVALID;
768     } else {
769       result = bytes_transferred;
770     }
771     last_tos_ = 0;
772     if (bytes_transferred > 0 && msg.msg_controllen > 0) {
773       for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr;
774            cmsg = CMSG_NXTHDR(&msg, cmsg)) {
775 #if BUILDFLAG(IS_APPLE)
776         if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVTOS) ||
777             (cmsg->cmsg_level == IPPROTO_IPV6 &&
778              cmsg->cmsg_type == IPV6_TCLASS)) {
779 #else
780         if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TOS) ||
781             (cmsg->cmsg_level == IPPROTO_IPV6 &&
782              cmsg->cmsg_type == IPV6_TCLASS)) {
783 #endif  // BUILDFLAG(IS_APPLE)
784           last_tos_ = *(reinterpret_cast<uint8_t*>(CMSG_DATA(cmsg)));
785         }
786       }
787     }
788   }
789 
790   LogRead(result, buf->data(), storage.addr_len, storage.addr);
791   return result;
792 }
793 
794 int UDPSocketPosix::InternalSendTo(IOBuffer* buf,
795                                    int buf_len,
796                                    const IPEndPoint* address) {
797   SockaddrStorage storage;
798   struct sockaddr* addr = storage.addr;
799   if (!address) {
800     addr = nullptr;
801     storage.addr_len = 0;
802   } else {
803     if (!address->ToSockAddr(storage.addr, &storage.addr_len)) {
804       int result = ERR_ADDRESS_INVALID;
805       LogWrite(result, nullptr, nullptr);
806       return result;
807     }
808   }
809 
810   int result = HANDLE_EINTR(sendto(socket_, buf->data(), buf_len, sendto_flags_,
811                                    addr, storage.addr_len));
812   if (result < 0)
813     result = MapSystemError(errno);
814   if (result != ERR_IO_PENDING)
815     LogWrite(result, buf->data(), address);
816   return result;
817 }
818 
819 int UDPSocketPosix::SetMulticastOptions() {
820   if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
821     int rv;
822     if (addr_family_ == AF_INET) {
823       u_char loop = 0;
824       rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP,
825                       &loop, sizeof(loop));
826     } else {
827       u_int loop = 0;
828       rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
829                       &loop, sizeof(loop));
830     }
831     if (rv < 0)
832       return MapSystemError(errno);
833   }
834   if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) {
835     int rv;
836     if (addr_family_ == AF_INET) {
837       u_char ttl = multicast_time_to_live_;
838       rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL,
839                       &ttl, sizeof(ttl));
840     } else {
841       // Signed integer. -1 to use route default.
842       int ttl = multicast_time_to_live_;
843       rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
844                       &ttl, sizeof(ttl));
845     }
846     if (rv < 0)
847       return MapSystemError(errno);
848   }
849   if (multicast_interface_ != 0) {
850     switch (addr_family_) {
851       case AF_INET: {
852         ip_mreqn mreq = {};
853         mreq.imr_ifindex = multicast_interface_;
854         mreq.imr_address.s_addr = htonl(INADDR_ANY);
855         int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
856                             reinterpret_cast<const char*>(&mreq), sizeof(mreq));
857         if (rv)
858           return MapSystemError(errno);
859         break;
860       }
861       case AF_INET6: {
862         uint32_t interface_index = multicast_interface_;
863         int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
864                             reinterpret_cast<const char*>(&interface_index),
865                             sizeof(interface_index));
866         if (rv)
867           return MapSystemError(errno);
868         break;
869       }
870       default:
871         NOTREACHED() << "Invalid address family";
872     }
873   }
874   return OK;
875 }
876 
877 int UDPSocketPosix::DoBind(const IPEndPoint& address) {
878   SockaddrStorage storage;
879   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
880     return ERR_ADDRESS_INVALID;
881   int rv = bind(socket_, storage.addr, storage.addr_len);
882   if (rv == 0)
883     return OK;
884   int last_error = errno;
885 #if BUILDFLAG(IS_CHROMEOS_ASH)
886   if (last_error == EINVAL)
887     return ERR_ADDRESS_IN_USE;
888 #elif BUILDFLAG(IS_APPLE)
889   if (last_error == EADDRNOTAVAIL)
890     return ERR_ADDRESS_IN_USE;
891 #endif
892   return MapSystemError(last_error);
893 }
894 
895 int UDPSocketPosix::RandomBind(const IPAddress& address) {
896   DCHECK_EQ(bind_type_, DatagramSocket::RANDOM_BIND);
897 
898   for (int i = 0; i < kBindRetries; ++i) {
899     int rv = DoBind(IPEndPoint(address, base::RandInt(kPortStart, kPortEnd)));
900     if (rv != ERR_ADDRESS_IN_USE)
901       return rv;
902   }
903 
904   return DoBind(IPEndPoint(address, 0));
905 }
906 
907 int UDPSocketPosix::JoinGroup(const IPAddress& group_address) const {
908   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
909   if (!is_connected())
910     return ERR_SOCKET_NOT_CONNECTED;
911 
912   switch (group_address.size()) {
913     case IPAddress::kIPv4AddressSize: {
914       if (addr_family_ != AF_INET)
915         return ERR_ADDRESS_INVALID;
916       ip_mreqn mreq = {};
917       mreq.imr_ifindex = multicast_interface_;
918       mreq.imr_address.s_addr = htonl(INADDR_ANY);
919       memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
920              IPAddress::kIPv4AddressSize);
921       int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
922                           &mreq, sizeof(mreq));
923       if (rv < 0)
924         return MapSystemError(errno);
925       return OK;
926     }
927     case IPAddress::kIPv6AddressSize: {
928       if (addr_family_ != AF_INET6)
929         return ERR_ADDRESS_INVALID;
930       ipv6_mreq mreq;
931       mreq.ipv6mr_interface = multicast_interface_;
932       memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
933              IPAddress::kIPv6AddressSize);
934       int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP,
935                           &mreq, sizeof(mreq));
936       if (rv < 0)
937         return MapSystemError(errno);
938       return OK;
939     }
940     default:
941       NOTREACHED() << "Invalid address family";
942   }
943 }
944 
945 int UDPSocketPosix::LeaveGroup(const IPAddress& group_address) const {
946   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
947 
948   if (!is_connected())
949     return ERR_SOCKET_NOT_CONNECTED;
950 
951   switch (group_address.size()) {
952     case IPAddress::kIPv4AddressSize: {
953       if (addr_family_ != AF_INET)
954         return ERR_ADDRESS_INVALID;
955       ip_mreqn mreq = {};
956       mreq.imr_ifindex = multicast_interface_;
957       mreq.imr_address.s_addr = INADDR_ANY;
958       memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
959              IPAddress::kIPv4AddressSize);
960       int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
961                           &mreq, sizeof(mreq));
962       if (rv < 0)
963         return MapSystemError(errno);
964       return OK;
965     }
966     case IPAddress::kIPv6AddressSize: {
967       if (addr_family_ != AF_INET6)
968         return ERR_ADDRESS_INVALID;
969       ipv6_mreq mreq;
970 #if BUILDFLAG(IS_FUCHSIA)
971       mreq.ipv6mr_interface = multicast_interface_;
972 #else   // BUILDFLAG(IS_FUCHSIA)
973       mreq.ipv6mr_interface = 0;  // 0 indicates default multicast interface.
974 #endif  // !BUILDFLAG(IS_FUCHSIA)
975       memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
976              IPAddress::kIPv6AddressSize);
977       int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
978                           &mreq, sizeof(mreq));
979       if (rv < 0)
980         return MapSystemError(errno);
981       return OK;
982     }
983     default:
984       NOTREACHED() << "Invalid address family";
985   }
986 }
987 
988 int UDPSocketPosix::SetMulticastInterface(uint32_t interface_index) {
989   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
990   if (is_connected())
991     return ERR_SOCKET_IS_CONNECTED;
992   multicast_interface_ = interface_index;
993   return OK;
994 }
995 
996 int UDPSocketPosix::SetMulticastTimeToLive(int time_to_live) {
997   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
998   if (is_connected())
999     return ERR_SOCKET_IS_CONNECTED;
1000 
1001   if (time_to_live < 0 || time_to_live > 255)
1002     return ERR_INVALID_ARGUMENT;
1003   multicast_time_to_live_ = time_to_live;
1004   return OK;
1005 }
1006 
1007 int UDPSocketPosix::SetMulticastLoopbackMode(bool loopback) {
1008   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1009   if (is_connected())
1010     return ERR_SOCKET_IS_CONNECTED;
1011 
1012   if (loopback)
1013     socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
1014   else
1015     socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
1016   return OK;
1017 }
1018 
1019 int UDPSocketPosix::SetDiffServCodePoint(DiffServCodePoint dscp) {
1020   return SetTos(dscp, ECN_NO_CHANGE);
1021 }
1022 
1023 int UDPSocketPosix::SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) {
1024   if (dscp == DSCP_NO_CHANGE && ecn == ECN_NO_CHANGE) {
1025     return OK;
1026   }
1027   int dscp_and_ecn = (dscp << 2) | ecn;
1028   socklen_t size = sizeof(dscp_and_ecn);
1029   if (dscp == DSCP_NO_CHANGE || ecn == ECN_NO_CHANGE) {
1030     int rv;
1031     if (addr_family_ == AF_INET) {
1032       rv = getsockopt(socket_, IPPROTO_IP, IP_TOS, &dscp_and_ecn, &size);
1033     } else {
1034       rv = getsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, &dscp_and_ecn, &size);
1035     }
1036     if (rv < 0) {
1037       return MapSystemError(errno);
1038     }
1039     if (dscp == DSCP_NO_CHANGE) {
1040       dscp_and_ecn &= ~ECN_LAST;
1041       dscp_and_ecn |= ecn;
1042     } else {
1043       dscp_and_ecn &= ECN_LAST;
1044       dscp_and_ecn |= (dscp << 2);
1045     }
1046   }
1047   // Set the IPv4 option in all cases to support dual-stack sockets.
1048   int rv = setsockopt(socket_, IPPROTO_IP, IP_TOS, &dscp_and_ecn,
1049                       sizeof(dscp_and_ecn));
1050   if (addr_family_ == AF_INET6) {
1051     // In the IPv6 case, the previous socksetopt may fail because of a lack of
1052     // dual-stack support. Therefore ignore the previous return value.
1053     rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS,
1054                     &dscp_and_ecn, sizeof(dscp_and_ecn));
1055   }
1056   if (rv < 0)
1057     return MapSystemError(errno);
1058   return OK;
1059 }
1060 
1061 int UDPSocketPosix::SetIPv6Only(bool ipv6_only) {
1062   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1063   if (is_connected()) {
1064     return ERR_SOCKET_IS_CONNECTED;
1065   }
1066   return net::SetIPv6Only(socket_, ipv6_only);
1067 }
1068 
1069 void UDPSocketPosix::DetachFromThread() {
1070   DETACH_FROM_THREAD(thread_checker_);
1071 }
1072 
1073 void UDPSocketPosix::ApplySocketTag(const SocketTag& tag) {
1074   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1075   if (socket_ != kInvalidSocket && tag != tag_) {
1076     tag.Apply(socket_);
1077   }
1078   tag_ = tag;
1079 }
1080 
1081 int UDPSocketPosix::SetIOSNetworkServiceType(int ios_network_service_type) {
1082   if (ios_network_service_type == 0) {
1083     return OK;
1084   }
1085 #if BUILDFLAG(IS_IOS)
1086   if (setsockopt(socket_, SOL_SOCKET, SO_NET_SERVICE_TYPE,
1087                  &ios_network_service_type, sizeof(ios_network_service_type))) {
1088     return MapSystemError(errno);
1089   }
1090 #endif  // BUILDFLAG(IS_IOS)
1091   return OK;
1092 }
1093 
1094 }  // namespace net
1095