• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "build/build_config.h"
6 
7 #if BUILDFLAG(IS_APPLE)
8 // This must be defined before including <netinet/in.h>
9 // to use IPV6_DONTFRAG, one of the IPv6 Sockets option introduced by RFC 3542
10 #define __APPLE_USE_RFC_3542
11 #endif  // BUILDFLAG(IS_APPLE)
12 
13 #include "net/socket/udp_socket_posix.h"
14 
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <net/if.h>
18 #include <netdb.h>
19 #include <netinet/in.h>
20 #include <sys/ioctl.h>
21 #include <sys/socket.h>
22 
23 #include <memory>
24 
25 #include "base/debug/alias.h"
26 #include "base/feature_list.h"
27 #include "base/files/file_util.h"
28 #include "base/functional/bind.h"
29 #include "base/functional/callback.h"
30 #include "base/functional/callback_helpers.h"
31 #include "base/logging.h"
32 #include "base/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