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