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