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