Line 0
Link Here
|
|
|
1 |
--- content/browser/geolocation/wifi_data_provider_freebsd.cc.orig 2012-12-06 11:09:56.159107947 -0500 |
2 |
+++ content/browser/geolocation/wifi_data_provider_freebsd.cc 2012-12-06 16:43:53.540918568 -0500 |
3 |
@@ -0,0 +1,198 @@ |
4 |
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
5 |
+// Use of this source code is governed by a BSD-style license that can be |
6 |
+// found in the LICENSE file. |
7 |
+ |
8 |
+// For FreeBSD we use the getifaddrs(3) to obtain the list of interfaces |
9 |
+// and then check for those with an 802.11 media type and able to return |
10 |
+// a list of stations. This is similar to ifconfig(8). |
11 |
+ |
12 |
+#include "content/browser/geolocation/wifi_data_provider_freebsd.h" |
13 |
+ |
14 |
+#include <stdio.h> |
15 |
+#include <stdlib.h> |
16 |
+#include <string.h> |
17 |
+#include <sys/types.h> |
18 |
+#include <sys/socket.h> |
19 |
+#include <sys/sockio.h> |
20 |
+#include <net/if.h> |
21 |
+#include <net/if_media.h> |
22 |
+#include <ifaddrs.h> |
23 |
+#include <net80211/ieee80211_ioctl.h> |
24 |
+#include <net/ethernet.h> |
25 |
+ |
26 |
+#include "base/utf_string_conversions.h" |
27 |
+#include "content/browser/geolocation/wifi_data_provider_common.h" |
28 |
+ |
29 |
+namespace { |
30 |
+// The time periods, in milliseconds, between successive polls of the wifi data. |
31 |
+const int kDefaultPollingInterval = 120000; // 2 mins |
32 |
+const int kNoChangePollingInterval = 300000; // 5 mins |
33 |
+const int kTwoNoChangePollingInterval = 600000; // 10 mins |
34 |
+const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s |
35 |
+ |
36 |
+// Convert a wifi frequency to the corresponding channel. |
37 |
+// Taken from wifi_data_provider_linux.cc where it says this was |
38 |
+// adapted from geolocaiton/wifilib.cc in googleclient (internal to google). |
39 |
+int frquency_to_channel(int frequency_Mhz) { |
40 |
+ if (frequency_Mhz >= 2412 && frequency_Mhz <= 2472) // Channels 1-13. |
41 |
+ return (frequency_Mhz - 2407) / 5; |
42 |
+ if (frequency_Mhz == 2484) |
43 |
+ return 14; |
44 |
+ if (frequency_Mhz > 5000 && frequency_Mhz < 6000) // .11a bands. |
45 |
+ return (frequency_Mhz - 5000) / 5; |
46 |
+ // Ignore everything else. |
47 |
+ return AccessPointData().channel; // invalid channel |
48 |
+} |
49 |
+ |
50 |
+// Provides the wifi API binding for FreeBSD. |
51 |
+class FreeBSDAccessPointData : public WifiDataProviderCommon::WlanApiInterface { |
52 |
+public: |
53 |
+ FreeBSDAccessPointData(); |
54 |
+ ~FreeBSDAccessPointData(); |
55 |
+ |
56 |
+ // this does nothing |
57 |
+ bool Init(); |
58 |
+ |
59 |
+ // get the AP data |
60 |
+ virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data); |
61 |
+ |
62 |
+private: |
63 |
+ DISALLOW_COPY_AND_ASSIGN(FreeBSDAccessPointData); |
64 |
+}; |
65 |
+ |
66 |
+FreeBSDAccessPointData::FreeBSDAccessPointData() { |
67 |
+} |
68 |
+ |
69 |
+FreeBSDAccessPointData::~FreeBSDAccessPointData() { |
70 |
+} |
71 |
+ |
72 |
+bool FreeBSDAccessPointData::Init() { |
73 |
+ return true; |
74 |
+} |
75 |
+ |
76 |
+bool FreeBSDAccessPointData::GetAccessPointData(WifiData::AccessPointDataSet* data) { |
77 |
+ bool res; |
78 |
+ char *dupn; |
79 |
+ struct ifaddrs *ifal, *ifa; |
80 |
+ struct ifreq ifr; |
81 |
+ struct ifmediareq ifmr; |
82 |
+ struct ieee80211req i802r; |
83 |
+ int s; |
84 |
+ char iscanbuf[32*1024], *vsr; |
85 |
+ unsigned len; |
86 |
+ AccessPointData apd; |
87 |
+ |
88 |
+ if (getifaddrs(&ifal) < 0) |
89 |
+ return NULL; |
90 |
+ |
91 |
+ res = false; |
92 |
+ dupn = NULL; |
93 |
+ for (ifa = ifal; ifa; ifa = ifa->ifa_next) { |
94 |
+ memset(&ifr, 0, sizeof(ifr)); |
95 |
+ |
96 |
+ if (dupn != NULL && strcmp(dupn, ifa->ifa_name) == 0) |
97 |
+ continue; |
98 |
+ dupn = ifa->ifa_name; |
99 |
+ |
100 |
+ strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); |
101 |
+ ifr.ifr_addr.sa_family = AF_LOCAL; |
102 |
+ |
103 |
+ if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) |
104 |
+ continue; |
105 |
+ |
106 |
+ (void) memset(&ifmr, 0, sizeof(ifmr)); |
107 |
+ (void) strncpy(ifmr.ifm_name, ifa->ifa_name, sizeof(ifmr.ifm_name)); |
108 |
+ |
109 |
+ if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { |
110 |
+ close(s); |
111 |
+ continue; |
112 |
+ } |
113 |
+ if (IFM_TYPE(ifmr.ifm_active) != IFM_IEEE80211) { |
114 |
+ close(s); |
115 |
+ continue; |
116 |
+ } |
117 |
+ |
118 |
+ (void) memset(&i802r, 0, sizeof(i802r)); |
119 |
+ (void) strncpy(i802r.i_name, ifa->ifa_name, sizeof(i802r.i_name)); |
120 |
+ i802r.i_type = IEEE80211_IOC_SCAN_RESULTS; |
121 |
+ i802r.i_data = iscanbuf; |
122 |
+ i802r.i_len = sizeof(iscanbuf); |
123 |
+ if (ioctl(s, SIOCG80211, &i802r) < 0) { |
124 |
+ close(s); |
125 |
+ continue; |
126 |
+ } |
127 |
+ |
128 |
+ close(s); |
129 |
+ |
130 |
+ vsr = (char *) i802r.i_data; |
131 |
+ len = i802r.i_len; |
132 |
+ while (len >= sizeof(struct ieee80211req_scan_result)) { |
133 |
+ struct ieee80211req_scan_result *isr; |
134 |
+ char *id; |
135 |
+ int idlen; |
136 |
+ char ssid[IEEE80211_NWID_LEN+1]; |
137 |
+ |
138 |
+ isr = (struct ieee80211req_scan_result *) vsr; |
139 |
+ |
140 |
+ if (isr->isr_meshid_len) { |
141 |
+ id = vsr + isr->isr_ie_off + isr->isr_ssid_len; |
142 |
+ idlen = isr->isr_meshid_len; |
143 |
+ } |
144 |
+ else { |
145 |
+ id = vsr + isr->isr_ie_off; |
146 |
+ idlen = isr->isr_ssid_len; |
147 |
+ } |
148 |
+ strncpy(ssid, id, idlen); |
149 |
+ ssid[idlen] = '\0'; |
150 |
+ apd.ssid = UTF8ToUTF16(ssid); |
151 |
+ apd.mac_address = MacAddressAsString16(isr->isr_bssid); |
152 |
+ apd.radio_signal_strength = (isr->isr_rssi/2) + isr->isr_noise; |
153 |
+ apd.signal_to_noise = apd.radio_signal_strength - isr->isr_noise; |
154 |
+ apd.channel = frquency_to_channel(isr->isr_freq); |
155 |
+ VLOG(1) << "FreeBSD access point: " |
156 |
+ << "SSID: " << apd.ssid << ", " |
157 |
+ << "MAC: " << apd.mac_address << ", " |
158 |
+ << "Strength: " << apd.radio_signal_strength << ":" |
159 |
+ << apd.signal_to_noise << ", " |
160 |
+ << "Channel: " << apd.channel; |
161 |
+ data->insert(apd); |
162 |
+ res = true; |
163 |
+ len -= isr->isr_len; |
164 |
+ vsr += isr->isr_len; |
165 |
+ } |
166 |
+ } |
167 |
+ |
168 |
+ freeifaddrs(ifal); |
169 |
+ |
170 |
+ return res; |
171 |
+} |
172 |
+ |
173 |
+} // namespace |
174 |
+ |
175 |
+// static |
176 |
+template<> |
177 |
+WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() { |
178 |
+ return new FreeBSDWifiDataProvider(); |
179 |
+} |
180 |
+ |
181 |
+FreeBSDWifiDataProvider::FreeBSDWifiDataProvider() { |
182 |
+} |
183 |
+ |
184 |
+FreeBSDWifiDataProvider::~FreeBSDWifiDataProvider() { |
185 |
+} |
186 |
+ |
187 |
+WifiDataProviderCommon::WlanApiInterface* FreeBSDWifiDataProvider::NewWlanApi() { |
188 |
+ |
189 |
+ scoped_ptr<FreeBSDAccessPointData> wlan_api(new FreeBSDAccessPointData); |
190 |
+ if (wlan_api->Init()) |
191 |
+ return wlan_api.release(); |
192 |
+ |
193 |
+ return NULL; |
194 |
+} |
195 |
+ |
196 |
+PollingPolicyInterface* FreeBSDWifiDataProvider::NewPollingPolicy() { |
197 |
+ return new GenericPollingPolicy<kDefaultPollingInterval, |
198 |
+ kNoChangePollingInterval, |
199 |
+ kTwoNoChangePollingInterval, |
200 |
+ kNoWifiPollingIntervalMilliseconds>; |
201 |
+} |