1 // Copyright 2018 The Chromium Authors. All rights reserved.
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 "services/network/p2p/socket_manager.h"
6 
7 #include <stddef.h>
8 
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/task/post_task.h"
13 #include "base/task/thread_pool.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "net/base/address_list.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/network_interfaces.h"
18 #include "net/base/sys_addrinfo.h"
19 #include "net/dns/host_resolver.h"
20 #include "net/log/net_log_source.h"
21 #include "net/log/net_log_with_source.h"
22 #include "net/socket/client_socket_factory.h"
23 #include "net/socket/datagram_client_socket.h"
24 #include "net/traffic_annotation/network_traffic_annotation.h"
25 #include "net/url_request/url_request_context.h"
26 #include "net/url_request/url_request_context_getter.h"
27 #include "services/network/p2p/socket.h"
28 #include "services/network/proxy_resolving_client_socket_factory.h"
29 #include "services/network/public/cpp/p2p_param_traits.h"
30 #include "third_party/webrtc/media/base/rtp_utils.h"
31 #include "third_party/webrtc/media/base/turn_utils.h"
32 
33 namespace network {
34 
35 namespace {
36 
37 // Used by GetDefaultLocalAddress as the target to connect to for getting the
38 // default local address. They are public DNS servers on the internet.
39 const uint8_t kPublicIPv4Host[] = {8, 8, 8, 8};
40 const uint8_t kPublicIPv6Host[] = {
41     0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88};
42 const int kPublicPort = 53;  // DNS port.
43 
44 // Experimentation shows that creating too many sockets creates odd problems
45 // because of resource exhaustion in the Unix sockets domain.
46 // Trouble has been seen on Linux at 3479 sockets in test, so leave a margin.
47 const int kMaxSimultaneousSockets = 3000;
48 
49 const size_t kMinRtcpHeaderLength = 8;
50 const size_t kDtlsRecordHeaderLength = 13;
51 
IsDtlsPacket(base::span<const uint8_t> data)52 bool IsDtlsPacket(base::span<const uint8_t> data) {
53   return data.size() >= kDtlsRecordHeaderLength &&
54          (data[0] > 19 && data[0] < 64);
55 }
56 
IsRtcpPacket(base::span<const uint8_t> data)57 bool IsRtcpPacket(base::span<const uint8_t> data) {
58   if (data.size() < kMinRtcpHeaderLength)
59     return false;
60 
61   int type = data[1] & 0x7F;
62   return type >= 64 && type < 96;
63 }
64 
65 // Names ending in ".local." are link-local and used with Multicast DNS as
66 // described in RFC6762 (https://tools.ietf.org/html/rfc6762#section-3).
67 constexpr char kLocalTld[] = ".local.";
68 
HasLocalTld(const std::string & host_name)69 bool HasLocalTld(const std::string& host_name) {
70   return EndsWith(host_name, kLocalTld, base::CompareCase::INSENSITIVE_ASCII);
71 }
72 
73 }  // namespace
74 
75 class P2PSocketManager::DnsRequest {
76  public:
77   using DoneCallback = base::OnceCallback<void(const net::IPAddressList&)>;
78 
DnsRequest(net::HostResolver * host_resolver,bool enable_mdns)79   DnsRequest(net::HostResolver* host_resolver, bool enable_mdns)
80       : resolver_(host_resolver), enable_mdns_(enable_mdns) {}
81 
Resolve(const std::string & host_name,DoneCallback done_callback)82   void Resolve(const std::string& host_name, DoneCallback done_callback) {
83     DCHECK(!done_callback.is_null());
84 
85     host_name_ = host_name;
86     done_callback_ = std::move(done_callback);
87 
88     // Return an error if it's an empty string.
89     if (host_name_.empty()) {
90       net::IPAddressList address_list;
91       std::move(done_callback_).Run(address_list);
92       return;
93     }
94 
95     // Add period at the end to make sure that we only resolve
96     // fully-qualified names.
97     if (host_name_.back() != '.')
98       host_name_ += '.';
99 
100     net::HostPortPair host(host_name_, 0);
101 
102     net::HostResolver::ResolveHostParameters parameters;
103     if (enable_mdns_ && HasLocalTld(host_name_)) {
104 #if BUILDFLAG(ENABLE_MDNS)
105       // HostResolver/MDnsClient expects a key without a trailing dot.
106       host.set_host(host_name_.substr(0, host_name_.size() - 1));
107       parameters.source = net::HostResolverSource::MULTICAST_DNS;
108 #endif  // ENABLE_MDNS
109     }
110     request_ =
111         resolver_->CreateRequest(host, net::NetLogWithSource(), parameters);
112 
113     int result = request_->Start(base::BindOnce(
114         &P2PSocketManager::DnsRequest::OnDone, base::Unretained(this)));
115     if (result != net::ERR_IO_PENDING)
116       OnDone(result);
117   }
118 
119  private:
OnDone(int result)120   void OnDone(int result) {
121     net::IPAddressList list;
122     const base::Optional<net::AddressList>& addresses =
123         request_->GetAddressResults();
124     if (result != net::OK || !addresses) {
125       LOG(ERROR) << "Failed to resolve address for " << host_name_
126                  << ", errorcode: " << result;
127       std::move(done_callback_).Run(list);
128       return;
129     }
130 
131     for (const auto& endpoint : *addresses) {
132       list.push_back(endpoint.address());
133     }
134     std::move(done_callback_).Run(list);
135   }
136 
137   std::string host_name_;
138   net::HostResolver* resolver_;
139   std::unique_ptr<net::HostResolver::ResolveHostRequest> request_;
140 
141   DoneCallback done_callback_;
142 
143   const bool enable_mdns_;
144 };
145 
P2PSocketManager(mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient> trusted_socket_manager_client,mojo::PendingReceiver<mojom::P2PTrustedSocketManager> trusted_socket_manager_receiver,mojo::PendingReceiver<mojom::P2PSocketManager> socket_manager_receiver,DeleteCallback delete_callback,net::URLRequestContext * url_request_context)146 P2PSocketManager::P2PSocketManager(
147     mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient>
148         trusted_socket_manager_client,
149     mojo::PendingReceiver<mojom::P2PTrustedSocketManager>
150         trusted_socket_manager_receiver,
151     mojo::PendingReceiver<mojom::P2PSocketManager> socket_manager_receiver,
152     DeleteCallback delete_callback,
153     net::URLRequestContext* url_request_context)
154     : delete_callback_(std::move(delete_callback)),
155       url_request_context_(url_request_context),
156       network_list_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
157           {base::MayBlock(), base::TaskPriority::USER_VISIBLE})),
158       trusted_socket_manager_client_(std::move(trusted_socket_manager_client)),
159       trusted_socket_manager_receiver_(
160           this,
161           std::move(trusted_socket_manager_receiver)),
162       socket_manager_receiver_(this, std::move(socket_manager_receiver)) {
163   trusted_socket_manager_receiver_.set_disconnect_handler(base::BindOnce(
164       &P2PSocketManager::OnConnectionError, base::Unretained(this)));
165   socket_manager_receiver_.set_disconnect_handler(base::BindOnce(
166       &P2PSocketManager::OnConnectionError, base::Unretained(this)));
167 }
168 
~P2PSocketManager()169 P2PSocketManager::~P2PSocketManager() {
170   // Reset the P2PSocketManager receiver before dropping pending dns requests.
171   socket_manager_receiver_.reset();
172 
173   sockets_.clear();
174   dns_requests_.clear();
175 
176   if (network_notification_client_)
177     net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
178 
179   proxy_resolving_socket_factory_.reset();
180 }
181 
OnNetworkChanged(net::NetworkChangeNotifier::ConnectionType type)182 void P2PSocketManager::OnNetworkChanged(
183     net::NetworkChangeNotifier::ConnectionType type) {
184   // NetworkChangeNotifier always emits CONNECTION_NONE notification whenever
185   // network configuration changes. All other notifications can be ignored.
186   if (type != net::NetworkChangeNotifier::CONNECTION_NONE)
187     return;
188 
189   // Notify the renderer about changes to list of network interfaces.
190   network_list_task_runner_->PostTask(
191       FROM_HERE, base::BindOnce(&P2PSocketManager::DoGetNetworkList,
192                                 weak_factory_.GetWeakPtr(),
193                                 base::ThreadTaskRunnerHandle::Get()));
194 }
195 
AddAcceptedConnection(std::unique_ptr<P2PSocket> accepted_connection)196 void P2PSocketManager::AddAcceptedConnection(
197     std::unique_ptr<P2PSocket> accepted_connection) {
198   sockets_[accepted_connection.get()] = std::move(accepted_connection);
199 }
200 
DestroySocket(P2PSocket * socket)201 void P2PSocketManager::DestroySocket(P2PSocket* socket) {
202   auto iter = sockets_.find(socket);
203   DCHECK(iter != sockets_.end());
204   sockets_.erase(iter);
205 }
206 
DumpPacket(base::span<const uint8_t> packet,bool incoming)207 void P2PSocketManager::DumpPacket(base::span<const uint8_t> packet,
208                                   bool incoming) {
209   if ((incoming && !dump_incoming_rtp_packet_) ||
210       (!incoming && !dump_outgoing_rtp_packet_)) {
211     return;
212   }
213 
214   if (IsDtlsPacket(packet) || IsRtcpPacket(packet))
215     return;
216 
217   size_t rtp_packet_pos = 0;
218   size_t rtp_packet_size = packet.size();
219   if (!cricket::UnwrapTurnPacket(packet.data(), packet.size(), &rtp_packet_pos,
220                                  &rtp_packet_size)) {
221     return;
222   }
223 
224   auto rtp_packet = packet.subspan(rtp_packet_pos, rtp_packet_size);
225 
226   size_t header_size = 0;
227   bool valid = cricket::ValidateRtpHeader(rtp_packet.data(), rtp_packet.size(),
228                                           &header_size);
229   if (!valid) {
230     NOTREACHED();
231     return;
232   }
233 
234   std::vector<uint8_t> header_buffer(rtp_packet.data(),
235                                      rtp_packet.data() + header_size);
236   trusted_socket_manager_client_->DumpPacket(header_buffer, rtp_packet.size(),
237                                              incoming);
238 }
239 
DoGetNetworkList(const base::WeakPtr<P2PSocketManager> & socket_manager,scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)240 void P2PSocketManager::DoGetNetworkList(
241     const base::WeakPtr<P2PSocketManager>& socket_manager,
242     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
243   net::NetworkInterfaceList list;
244   if (!net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
245     LOG(ERROR) << "GetNetworkList failed.";
246     return;
247   }
248   net::IPAddress default_ipv4_local_address = GetDefaultLocalAddress(AF_INET);
249   net::IPAddress default_ipv6_local_address = GetDefaultLocalAddress(AF_INET6);
250   main_task_runner->PostTask(
251       FROM_HERE,
252       base::BindOnce(&P2PSocketManager::SendNetworkList, socket_manager, list,
253                      default_ipv4_local_address, default_ipv6_local_address));
254 }
255 
SendNetworkList(const net::NetworkInterfaceList & list,const net::IPAddress & default_ipv4_local_address,const net::IPAddress & default_ipv6_local_address)256 void P2PSocketManager::SendNetworkList(
257     const net::NetworkInterfaceList& list,
258     const net::IPAddress& default_ipv4_local_address,
259     const net::IPAddress& default_ipv6_local_address) {
260   network_notification_client_->NetworkListChanged(
261       list, default_ipv4_local_address, default_ipv6_local_address);
262 }
263 
StartNetworkNotifications(mojo::PendingRemote<mojom::P2PNetworkNotificationClient> client)264 void P2PSocketManager::StartNetworkNotifications(
265     mojo::PendingRemote<mojom::P2PNetworkNotificationClient> client) {
266   DCHECK(!network_notification_client_);
267   network_notification_client_.Bind(std::move(client));
268   network_notification_client_.set_disconnect_handler(base::BindOnce(
269       &P2PSocketManager::NetworkNotificationClientConnectionError,
270       base::Unretained(this)));
271 
272   net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
273 
274   network_list_task_runner_->PostTask(
275       FROM_HERE, base::BindOnce(&P2PSocketManager::DoGetNetworkList,
276                                 weak_factory_.GetWeakPtr(),
277                                 base::ThreadTaskRunnerHandle::Get()));
278 }
279 
GetHostAddress(const std::string & host_name,bool enable_mdns,mojom::P2PSocketManager::GetHostAddressCallback callback)280 void P2PSocketManager::GetHostAddress(
281     const std::string& host_name,
282     bool enable_mdns,
283     mojom::P2PSocketManager::GetHostAddressCallback callback) {
284   auto request = std::make_unique<DnsRequest>(
285       url_request_context_->host_resolver(), enable_mdns);
286   DnsRequest* request_ptr = request.get();
287   dns_requests_.insert(std::move(request));
288   request_ptr->Resolve(
289       host_name,
290       base::BindOnce(&P2PSocketManager::OnAddressResolved,
291                      base::Unretained(this), request_ptr, std::move(callback)));
292 }
293 
CreateSocket(P2PSocketType type,const net::IPEndPoint & local_address,const P2PPortRange & port_range,const P2PHostAndIPEndPoint & remote_address,mojo::PendingRemote<mojom::P2PSocketClient> client,mojo::PendingReceiver<mojom::P2PSocket> receiver)294 void P2PSocketManager::CreateSocket(
295     P2PSocketType type,
296     const net::IPEndPoint& local_address,
297     const P2PPortRange& port_range,
298     const P2PHostAndIPEndPoint& remote_address,
299     mojo::PendingRemote<mojom::P2PSocketClient> client,
300     mojo::PendingReceiver<mojom::P2PSocket> receiver) {
301   if (port_range.min_port > port_range.max_port ||
302       (port_range.min_port == 0 && port_range.max_port != 0)) {
303     trusted_socket_manager_client_->InvalidSocketPortRangeRequested();
304     return;
305   }
306 
307   if (!proxy_resolving_socket_factory_) {
308     proxy_resolving_socket_factory_ =
309         std::make_unique<ProxyResolvingClientSocketFactory>(
310             url_request_context_);
311   }
312   if (sockets_.size() > kMaxSimultaneousSockets) {
313     LOG(ERROR) << "Too many sockets created";
314     return;
315   }
316   std::unique_ptr<P2PSocket> socket =
317       P2PSocket::Create(this, std::move(client), std::move(receiver), type,
318                         url_request_context_->net_log(),
319                         proxy_resolving_socket_factory_.get(), &throttler_);
320 
321   if (!socket)
322     return;
323 
324   P2PSocket* socket_ptr = socket.get();
325   sockets_[socket_ptr] = std::move(socket);
326 
327   // Init() may call SocketManager::DestroySocket(), so it must be called after
328   // adding the socket to |sockets_|.
329   socket_ptr->Init(local_address, port_range.min_port, port_range.max_port,
330                    remote_address);
331 }
332 
StartRtpDump(bool incoming,bool outgoing)333 void P2PSocketManager::StartRtpDump(bool incoming, bool outgoing) {
334   dump_incoming_rtp_packet_ |= incoming;
335   dump_outgoing_rtp_packet_ |= outgoing;
336 }
337 
StopRtpDump(bool incoming,bool outgoing)338 void P2PSocketManager::StopRtpDump(bool incoming, bool outgoing) {
339   dump_incoming_rtp_packet_ &= !incoming;
340   dump_outgoing_rtp_packet_ &= !outgoing;
341 }
342 
NetworkNotificationClientConnectionError()343 void P2PSocketManager::NetworkNotificationClientConnectionError() {
344   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
345 }
346 
GetDefaultLocalAddress(int family)347 net::IPAddress P2PSocketManager::GetDefaultLocalAddress(int family) {
348   DCHECK(family == AF_INET || family == AF_INET6);
349 
350   // Creation and connection of a UDP socket might be janky.
351   // DCHECK(network_list_task_runner_->RunsTasksInCurrentSequence());
352 
353   auto socket =
354       net::ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
355           net::DatagramSocket::DEFAULT_BIND, nullptr, net::NetLogSource());
356 
357   net::IPAddress ip_address;
358   if (family == AF_INET) {
359     ip_address = net::IPAddress(kPublicIPv4Host);
360   } else {
361     ip_address = net::IPAddress(kPublicIPv6Host);
362   }
363 
364   if (socket->Connect(net::IPEndPoint(ip_address, kPublicPort)) != net::OK) {
365     return net::IPAddress();
366   }
367 
368   net::IPEndPoint local_address;
369   if (socket->GetLocalAddress(&local_address) != net::OK)
370     return net::IPAddress();
371 
372   return local_address.address();
373 }
374 
OnAddressResolved(DnsRequest * request,mojom::P2PSocketManager::GetHostAddressCallback callback,const net::IPAddressList & addresses)375 void P2PSocketManager::OnAddressResolved(
376     DnsRequest* request,
377     mojom::P2PSocketManager::GetHostAddressCallback callback,
378     const net::IPAddressList& addresses) {
379   std::move(callback).Run(addresses);
380 
381   dns_requests_.erase(dns_requests_.find(request));
382 }
383 
OnConnectionError()384 void P2PSocketManager::OnConnectionError() {
385   std::move(delete_callback_).Run(this);
386 }
387 
388 }  // namespace network
389