Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 extern "C" {
7 #include <arpa/inet.h>
8 #include "r_types.h"
9 #include "stun.h"
10 #include "addrs.h"
11 }
13 #include <vector>
14 #include <string>
15 #include "nsINetworkManager.h"
16 #include "nsINetworkInterfaceListService.h"
17 #include "runnable_utils.h"
18 #include "nsCOMPtr.h"
19 #include "nsMemory.h"
20 #include "nsThreadUtils.h"
21 #include "nsServiceManagerUtils.h"
22 #include "mozilla/SyncRunnable.h"
24 namespace {
25 struct NetworkInterface {
26 struct sockaddr_in addr;
27 std::string name;
28 // See NR_INTERFACE_TYPE_* in nICEr/src/net/local_addrs.h
29 int type;
30 };
32 nsresult
33 GetInterfaces(std::vector<NetworkInterface>* aInterfaces)
34 {
35 MOZ_ASSERT(aInterfaces);
37 // Obtain network interfaces from network manager.
38 nsresult rv;
39 nsCOMPtr<nsINetworkInterfaceListService> listService =
40 do_GetService("@mozilla.org/network/interface-list-service;1", &rv);
41 NS_ENSURE_SUCCESS(rv, rv);
43 int32_t flags =
44 nsINetworkInterfaceListService::LIST_NOT_INCLUDE_SUPL_INTERFACES |
45 nsINetworkInterfaceListService::LIST_NOT_INCLUDE_MMS_INTERFACES |
46 nsINetworkInterfaceListService::LIST_NOT_INCLUDE_IMS_INTERFACES |
47 nsINetworkInterfaceListService::LIST_NOT_INCLUDE_DUN_INTERFACES;
48 nsCOMPtr<nsINetworkInterfaceList> networkList;
49 NS_ENSURE_SUCCESS(listService->GetDataInterfaceList(flags,
50 getter_AddRefs(networkList)),
51 NS_ERROR_FAILURE);
53 // Translate nsINetworkInterfaceList to NetworkInterface.
54 int32_t listLength;
55 NS_ENSURE_SUCCESS(networkList->GetNumberOfInterface(&listLength),
56 NS_ERROR_FAILURE);
57 aInterfaces->clear();
59 for (int32_t i = 0; i < listLength; i++) {
60 nsCOMPtr<nsINetworkInterface> iface;
61 if (NS_FAILED(networkList->GetInterface(i, getter_AddRefs(iface)))) {
62 continue;
63 }
65 char16_t **ips = nullptr;
66 uint32_t *prefixs = nullptr;
67 uint32_t count = 0;
68 bool isAddressGot = false;
69 NetworkInterface interface;
70 memset(&(interface.addr), 0, sizeof(interface.addr));
71 interface.addr.sin_family = AF_INET;
73 if (NS_FAILED(iface->GetAddresses(&ips, &prefixs, &count))) {
74 continue;
75 }
77 for (uint32_t j = 0; j < count; j++) {
78 nsAutoString ip;
80 ip.Assign(ips[j]);
81 if (inet_pton(AF_INET, NS_ConvertUTF16toUTF8(ip).get(),
82 &(interface.addr.sin_addr.s_addr)) == 1) {
83 isAddressGot = true;
84 break;
85 }
86 }
88 nsMemory::Free(prefixs);
89 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, ips);
91 if (!isAddressGot) {
92 continue;
93 }
95 nsAutoString ifaceName;
96 if (NS_FAILED(iface->GetName(ifaceName))) {
97 continue;
98 }
99 interface.name = NS_ConvertUTF16toUTF8(ifaceName).get();
101 int32_t type;
102 if (NS_FAILED(iface->GetType(&type))) {
103 continue;
104 }
105 switch (type) {
106 case nsINetworkInterface::NETWORK_TYPE_WIFI:
107 interface.type = NR_INTERFACE_TYPE_WIFI;
108 break;
109 case nsINetworkInterface::NETWORK_TYPE_MOBILE:
110 interface.type = NR_INTERFACE_TYPE_MOBILE;
111 break;
112 }
114 aInterfaces->push_back(interface);
115 }
116 return NS_OK;
117 }
118 } // anonymous namespace
120 int
121 nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs,
122 int aDropLoopback, int* aCount)
123 {
124 nsresult rv;
125 int r;
127 // Get network interface list.
128 std::vector<NetworkInterface> interfaces;
129 nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
130 mozilla::SyncRunnable::DispatchToThread(
131 mainThread.get(),
132 mozilla::WrapRunnableNMRet(&GetInterfaces, &interfaces, &rv),
133 false);
134 if (NS_FAILED(rv)) {
135 return R_FAILED;
136 }
138 // Translate to nr_transport_addr.
139 int32_t n = 0;
140 size_t num_interface = std::min(interfaces.size(), (size_t)aMaxAddrs);
141 for (size_t i = 0; i < num_interface; ++i) {
142 NetworkInterface &interface = interfaces[i];
143 if (nr_sockaddr_to_transport_addr((sockaddr*)&(interface.addr),
144 sizeof(struct sockaddr_in),
145 IPPROTO_UDP, 0, &(aAddrs[n].addr))) {
146 r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address");
147 return R_FAILED;
148 }
149 strlcpy(aAddrs[n].addr.ifname, interface.name.c_str(),
150 sizeof(aAddrs[n].addr.ifname));
151 aAddrs[n].interface.type = interface.type;
152 aAddrs[n].interface.estimated_speed = 0;
153 n++;
154 }
156 *aCount = n;
157 r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aCount);
158 if (r != 0) {
159 return r;
160 }
162 for (int i = 0; i < *aCount; ++i) {
163 char typestr[100];
164 nr_local_addr_fmt_info_string(aAddrs + i, typestr, sizeof(typestr));
165 r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n",
166 i, aAddrs[i].addr.as_string, aAddrs[i].addr.ifname, typestr);
167 }
169 return 0;
170 }