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