Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: content/browser/geolocation/gateway_data_provider_linux.cc

Issue 6597044: Revert 76228 - Move core pieces of geolocation from chrome to content.This is... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 // Provides MAC addresses of connected routers by using the /proc/net/
6 // directory which contains files with network information.
7 // This directory is used in most Linux based operating systems.
8
9 #include "content/browser/geolocation/gateway_data_provider_linux.h"
10
11 #include <algorithm>
12 #include <arpa/inet.h>
13 #include <net/if.h>
14 #include <net/if_arp.h>
15 #include <set>
16 #include <string>
17 #include <sys/ioctl.h>
18 #include <vector>
19
20 #include "base/command_line.h"
21 #include "base/file_util.h"
22 #include "base/string_number_conversions.h"
23 #include "base/string_tokenizer.h"
24 #include "base/string_util.h"
25 #include "base/utf_string_conversions.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "content/browser/geolocation/empty_device_data_provider.h"
28 #include "content/browser/geolocation/gateway_data_provider_common.h"
29
30 namespace {
31 const unsigned int kMaxArpIterations = 30;
32 const unsigned int kMaxRouteIterations = 20;
33 const char kNoGateway[] = "00000000";
34 const char kArpFilePath[] = "/proc/net/arp";
35 const char kRouteFilePath[] = "/proc/net/route";
36
37 // Converts an IP address held in a little endian paired hex format to period
38 // separated decimal format. For example 0101A8C0 becomes 192.168.1.1
39 std::string HexToIpv4Format(std::string& hex_address) {
40 if (hex_address.size() != 8)
41 return "";
42 std::vector<uint8> bytes;
43 if (!base::HexStringToBytes(hex_address, &bytes) ||
44 bytes.size() != 4) {
45 return "";
46 }
47 struct in_addr in;
48 uint32 ip_native_endian;
49 memcpy(&ip_native_endian, &bytes[0], 4);
50 in.s_addr = htonl(ip_native_endian);
51 return inet_ntoa(in);
52 }
53
54 // TODO(joth): Cache the sets of gateways and MAC addresses to avoid reading
55 // through the arp table when the routing table hasn't changed.
56 class LinuxGatewayApi : public GatewayDataProviderCommon::GatewayApiInterface {
57 public:
58 LinuxGatewayApi() {}
59 virtual ~LinuxGatewayApi() {}
60
61 static LinuxGatewayApi* Create() {
62 return new LinuxGatewayApi();
63 }
64
65 // GatewayApiInterface
66 virtual bool GetRouterData(GatewayData::RouterDataSet* data);
67
68 private:
69 DISALLOW_COPY_AND_ASSIGN(LinuxGatewayApi);
70 };
71
72 // Gets a set of gateways using data from /proc/net/route
73 // Returns false if we cannot read the route file or we cannot classify the
74 // type of network adapter.
75 // Routing data is held in the following format
76 // Note: "|" represents a delimeter.
77 // Iface|Destination|Gateway|Flags|RefCnt|Use|Metric|Mask|MTU|Window|IRTT
78 // The delimiter for this table is "\t".
79 // ioctl calls are used to verify the type of network adapter, using interface
80 // names from the route table.
81 bool GetGateways(std::set<std::string>* gateways) {
82 FilePath route_file_path(kRouteFilePath);
83 std::string route_file;
84 if (!file_util::ReadFileToString(route_file_path, &route_file)) {
85 // Unable to read file.
86 return false;
87 }
88 StringTokenizer tokenized_route_file(route_file, "\n");
89 std::vector<std::string> route_data;
90 // Remove column labels.
91 tokenized_route_file.GetNext();
92
93 // Get rows of data.
94 while (tokenized_route_file.GetNext() &&
95 route_data.size() < kMaxRouteIterations)
96 route_data.push_back(tokenized_route_file.token());
97
98 if (route_data.empty()) {
99 // Having no data is not an error case.
100 return true;
101 }
102
103 int sock;
104 sock = socket(AF_INET, SOCK_STREAM, 0);
105 if (sock == -1)
106 return false;
107 struct ifreq network_device;
108
109 for (size_t j = 0; j < route_data.size(); ++j) {
110 // Get gateway address.
111 std::string gateway;
112 StringTokenizer tokenized_route_data(route_data[j], "\t");
113 // Check if device is an Ethernet device.
114 if (!tokenized_route_data.GetNext()) // Get Iface.
115 continue;
116 // Ensure space for the null term too.
117 if (tokenized_route_data.token().size() >=
118 arraysize(network_device.ifr_name))
119 continue;
120 memset(&network_device, 0, sizeof(network_device));
121 base::strlcpy(network_device.ifr_name,
122 tokenized_route_data.token().c_str(),
123 arraysize(network_device.ifr_name));
124 if (ioctl(sock, SIOCGIFHWADDR,
125 reinterpret_cast<char*>(&network_device)) < 0) {
126 // Could not get device type.
127 continue;
128 }
129 if (network_device.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
130 // Device is not an Ethernet device.
131 continue;
132 }
133 if (!tokenized_route_data.GetNext()) // Skip Destination.
134 continue;
135 if (!tokenized_route_data.GetNext()) // Get Gateway.
136 continue;
137 gateway = tokenized_route_data.token();
138 if (gateway != kNoGateway) {
139 // TODO(joth): Currently only works for gateways using IPv4.
140 std::string gateway_int_format = HexToIpv4Format(gateway);
141 if (!gateway_int_format.empty())
142 gateways->insert(gateway_int_format);
143 }
144 }
145
146 close(sock);
147 return true;
148 }
149
150 // Gets a RouterDataSet containing MAC addresses related to any connected
151 // routers. Returns false if we cannot read the arp file.
152 // The /proc/net/arp file contains arp data in the following format
153 // Note: "|" represents a delimeter.
154 // IP address|HW type|Flags|HW address|Mask|Device
155 // The delimiter for this table is " ".
156 bool GetMacAddresses(GatewayData::RouterDataSet* data,
157 std::set<std::string>* gateways) {
158 // Find MAC addresses of routers
159 FilePath arp_file_path(kArpFilePath);
160 std::string arp_file_out;
161 if (!file_util::ReadFileToString(arp_file_path, &arp_file_out)) {
162 // Unable to read file.
163 return false;
164 }
165 StringTokenizer tokenized_arp_file(arp_file_out, "\n");
166 std::vector<std::string> arp_data;
167 // Remove column labels.
168 tokenized_arp_file.GetNext();
169
170 // Get rows of data.
171 while (tokenized_arp_file.GetNext() && arp_data.size() < kMaxArpIterations)
172 arp_data.push_back(tokenized_arp_file.token());
173
174 for (size_t k = 0; k < arp_data.size(); k++) {
175 std::string ip_address;
176 StringTokenizer tokenized_arp_data(arp_data[k], " ");
177 if (!tokenized_arp_data.GetNext()) // Get IP address.
178 continue;
179 ip_address = tokenized_arp_data.token();
180 if (gateways->find(ip_address) == gateways->end())
181 continue;
182 if (!tokenized_arp_data.GetNext()) // Skip HW type.
183 continue;
184 if (!tokenized_arp_data.GetNext()) // Skip flags.
185 continue;
186 if (!tokenized_arp_data.GetNext()) // Get HW address.
187 continue;
188 RouterData router;
189 std::string mac_add;
190 mac_add = tokenized_arp_data.token();
191 std::replace(mac_add.begin(), mac_add.end(), ':', '-');
192 router.mac_address = UTF8ToUTF16(mac_add);
193 data->insert(router);
194 }
195
196 return true;
197 }
198
199 bool LinuxGatewayApi::GetRouterData(GatewayData::RouterDataSet* data) {
200 std::set<std::string> gateways;
201 if (!GetGateways(&gateways))
202 return false;
203 if (gateways.empty())
204 return true;
205 return GetMacAddresses(data, &gateways);
206 }
207 } // namespace
208
209 // static
210 template<>
211 GatewayDataProviderImplBase* GatewayDataProvider::DefaultFactoryFunction() {
212 if (!CommandLine::ForCurrentProcess()
213 ->HasSwitch(switches::kExperimentalLocationFeatures))
214 return new EmptyDeviceDataProvider<GatewayData>();
215 return new GatewayDataProviderLinux();
216 }
217
218 GatewayDataProviderLinux::GatewayDataProviderLinux() {
219 }
220
221 GatewayDataProviderLinux::~GatewayDataProviderLinux() {
222 }
223
224 GatewayDataProviderCommon::GatewayApiInterface*
225 GatewayDataProviderLinux::NewGatewayApi() {
226 return LinuxGatewayApi::Create();
227 }
OLDNEW
« no previous file with comments | « content/browser/geolocation/gateway_data_provider_linux.h ('k') | content/browser/geolocation/gateway_data_provider_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698