chromium 11.0.969.72
[chromium.git] / patches / patch-chrome_browser_geolocation_gateway__data__provider__bsd.cc
1 $NetBSD$
2
3 --- chrome/browser/geolocation/gateway_data_provider_bsd.cc.orig        2011-04-26 05:17:13.000000000 +0000
4 +++ chrome/browser/geolocation/gateway_data_provider_bsd.cc
5 @@ -0,0 +1,188 @@
6 +// Copyright (c) 2010 The Chromium Authors. All rights reserved.
7 +// Use of this source code is governed by a BSD-style license that can be
8 +// found in the LICENSE file.
9 +
10 +// Provides MAC addresses of connected routers by using the /proc/net/
11 +// directory which contains files with network information.
12 +// This directory is used in most BSD based operating systems.
13 +
14 +#include "chrome/browser/geolocation/gateway_data_provider_bsd.h"
15 +
16 +#include <sys/types.h>
17 +#include <sys/param.h>
18 +#include <sys/sysctl.h>
19 +#include <unistd.h>
20 +#include <sys/time.h>
21 +#include <sys/socket.h>
22 +#include <net/if.h>
23 +#include <net/if_dl.h>
24 +#include <net/route.h>
25 +#include <net/ethernet.h>
26 +#include <netinet/in.h>
27 +#include <netinet/if_ether.h>
28 +#include <arpa/inet.h>
29 +#include <string.h>
30 +#include <unistd.h>
31 +#include <stdlib.h>
32 +
33 +#include <algorithm>
34 +#include <set>
35 +#include <string>
36 +#include <vector>
37 +
38 +#include "base/command_line.h"
39 +#include "base/utf_string_conversions.h"
40 +#include "chrome/browser/geolocation/empty_device_data_provider.h"
41 +#include "chrome/browser/geolocation/gateway_data_provider_common.h"
42 +#include "chrome/common/chrome_switches.h"
43 +
44 +#ifndef SA_SIZE
45 +#define SA_SIZE(sa)                                            \
46 +       ((!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ?    \
47 +        sizeof(long) :                                         \
48 +        1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1)))
49 +#endif
50 +
51 +namespace {
52 +
53 +// TODO(joth): Cache the sets of gateways and MAC addresses to avoid reading
54 +// through the arp table when the routing table hasn't changed.
55 +class BSDGatewayApi : public GatewayDataProviderCommon::GatewayApiInterface {
56 + public:
57 +  BSDGatewayApi() {}
58 +  virtual ~BSDGatewayApi() {}
59 +
60 +  static BSDGatewayApi* Create() {
61 +    return new BSDGatewayApi();
62 +  }
63 +
64 +  // GatewayApiInterface
65 +  virtual bool GetRouterData(GatewayData::RouterDataSet* data);
66 +
67 + private:
68 +  DISALLOW_COPY_AND_ASSIGN(BSDGatewayApi);
69 +};
70 +
71 +bool GetGateways(std::set<std::string>* gateways) {
72 +  struct rt_msghdr *rtm;
73 +  size_t needed;
74 +  int mib[6];
75 +  char *buf, *next, *lim;
76 +
77 +  struct sockaddr *dst;
78 +  struct sockaddr_inarp *gw;
79 +
80 +  mib[0] = CTL_NET;
81 +  mib[1] = PF_ROUTE;
82 +  mib[2] = 0;
83 +  mib[3] = AF_INET;
84 +  mib[4] = NET_RT_DUMP;
85 +  mib[5] = 0;
86 +
87 +  if (sysctl(mib, 6, NULL, &needed, NULL, 0) > 0) 
88 +    return false;
89 +
90 +  if ((buf = (char *)malloc(needed)) == 0)
91 +    return false;
92 +
93 +  if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
94 +    return false;
95 +
96 +  lim = buf + needed;
97 +  for (next = buf; next < lim; next += rtm->rtm_msglen) {
98 +    rtm = (struct rt_msghdr *) next;
99 +    if (!(rtm->rtm_flags & RTF_GATEWAY))
100 +      continue;
101 +
102 +    dst = (struct sockaddr *)(rtm + 1);
103 +    gw = (struct sockaddr_inarp *)(dst->sa_len + (char *)dst);
104 +
105 +    gateways->insert(inet_ntoa(gw->sin_addr));
106 +
107 +  }
108 +  free(buf);
109 +  return true;
110 +}
111 +
112 +// Gets a RouterDataSet containing MAC addresses related to any connected
113 +// routers. Returns false if we cannot read the arp file.
114 +// The /proc/net/arp file contains arp data in the following format
115 +// Note: "|" represents a delimeter.
116 +// IP address|HW type|Flags|HW address|Mask|Device
117 +// The delimiter for this table is " ".
118 +bool GetMacAddresses(GatewayData::RouterDataSet* data,
119 +                     std::set<std::string>* gateways) {
120 +  struct rt_msghdr *rtm;
121 +  size_t needed;
122 +  int    mib[6];
123 +  char  *buf, *next, *lim;
124 +
125 +  struct sockaddr_inarp *sin;
126 +  struct sockaddr_dl *sdl;
127 +
128 +  mib[0] = CTL_NET;
129 +  mib[1] = PF_ROUTE;
130 +  mib[2] = 0;
131 +  mib[3] = AF_INET;
132 +  mib[4] = NET_RT_FLAGS;
133 +  mib[5] = 0;
134 +
135 +  if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
136 +    return false;
137 +
138 +  if ((buf = (char *)malloc(needed)) == 0)
139 +    return false;
140 +
141 +  if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
142 +    return false;
143 +
144 +  lim  = buf + needed;
145 +  for (next = buf; next < lim; next += rtm->rtm_msglen) {
146 +    rtm = (struct rt_msghdr *)next;
147 +    sin = (struct sockaddr_inarp *)(rtm + 1);
148 +
149 +    std::string ip_addr = inet_ntoa(sin->sin_addr);
150 +    if (gateways->find(ip_addr) == gateways->end())
151 +      continue;
152 +
153 +    sdl = (struct sockaddr_dl *)((char *)sin + SA_SIZE(sin));
154 +    std::string mac_addr = ether_ntoa((struct ether_addr *)LLADDR(sdl));
155 +
156 +    std::replace(mac_addr.begin(), mac_addr.end(), ':', '-');
157 +    RouterData router;
158 +    router.mac_address = UTF8ToUTF16(mac_addr);
159 +    data->insert(router);
160 +  }
161 +
162 +  return true;
163 +}
164 +
165 +bool BSDGatewayApi::GetRouterData(GatewayData::RouterDataSet* data) {
166 +  std::set<std::string> gateways;
167 +  if (!GetGateways(&gateways))
168 +    return false;
169 +  if (gateways.empty())
170 +    return true;
171 +  return GetMacAddresses(data, &gateways);
172 +}
173 +} // namespace
174 +
175 +// static
176 +template<>
177 +GatewayDataProviderImplBase* GatewayDataProvider::DefaultFactoryFunction() {
178 +  if (!CommandLine::ForCurrentProcess()
179 +      ->HasSwitch(switches::kExperimentalLocationFeatures))
180 +    return new EmptyDeviceDataProvider<GatewayData>();
181 +  return new GatewayDataProviderBSD();
182 +}
183 +
184 +GatewayDataProviderBSD::GatewayDataProviderBSD() {
185 +}
186 +
187 +GatewayDataProviderBSD::~GatewayDataProviderBSD() {
188 +}
189 +
190 +GatewayDataProviderCommon::GatewayApiInterface*
191 +    GatewayDataProviderBSD::NewGatewayApi() {
192 +  return BSDGatewayApi::Create();
193 +}