Backout rev 149f006c0541. a=backout
[gecko.git] / netwerk / wifi / nsWifiScannerFreeBSD.cpp
blobbdf171eb6cf5139c3f88a5f16bfeaf213269b3d0
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // Developed by J.R. Oldroyd <fbsd@opal.com>, December 2012.
7 // For FreeBSD we use the getifaddrs(3) to obtain the list of interfaces
8 // and then check for those with an 802.11 media type and able to return
9 // a list of stations. This is similar to ifconfig(8).
11 #include <sys/types.h>
12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
14 #include <net/if.h>
15 #include <net/if_media.h>
16 #include <net80211/ieee80211_ioctl.h>
18 #include <ifaddrs.h>
19 #include <string.h>
20 #include <unistd.h>
22 #include "nsWifiAccessPoint.h"
24 using namespace mozilla;
26 static nsresult
27 FreeBSDGetAccessPointData(nsCOMArray<nsWifiAccessPoint> &accessPoints)
29 // get list of interfaces
30 struct ifaddrs *ifal;
31 if (getifaddrs(&ifal) < 0) {
32 return NS_ERROR_FAILURE;
35 accessPoints.Clear();
37 // loop through the interfaces
38 nsresult rv = NS_ERROR_FAILURE;
39 struct ifaddrs *ifa;
40 for (ifa = ifal; ifa; ifa = ifa->ifa_next) {
41 // limit to one interface per address
42 if (ifa->ifa_addr->sa_family != AF_LINK) {
43 continue;
46 // store interface name in socket structure
47 struct ifreq ifr;
48 memset(&ifr, 0, sizeof(ifr));
49 strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
50 ifr.ifr_addr.sa_family = AF_LOCAL;
52 // open socket to interface
53 int s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
54 if (s < 0) {
55 continue;
58 // clear interface media structure
59 struct ifmediareq ifmr;
60 memset(&ifmr, 0, sizeof(ifmr));
61 strncpy(ifmr.ifm_name, ifa->ifa_name, sizeof(ifmr.ifm_name));
63 // get interface media information
64 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
65 close(s);
66 continue;
69 // check interface is a WiFi interface
70 if (IFM_TYPE(ifmr.ifm_active) != IFM_IEEE80211) {
71 close(s);
72 continue;
75 // perform WiFi scan
76 struct ieee80211req i802r;
77 char iscanbuf[32*1024];
78 memset(&i802r, 0, sizeof(i802r));
79 strncpy(i802r.i_name, ifa->ifa_name, sizeof(i802r.i_name));
80 i802r.i_type = IEEE80211_IOC_SCAN_RESULTS;
81 i802r.i_data = iscanbuf;
82 i802r.i_len = sizeof(iscanbuf);
83 if (ioctl(s, SIOCG80211, &i802r) < 0) {
84 close(s);
85 continue;
88 // close socket
89 close(s);
91 // loop through WiFi networks and build geoloc-lookup structure
92 char *vsr = (char *) i802r.i_data;
93 unsigned len = i802r.i_len;
94 while (len >= sizeof(struct ieee80211req_scan_result)) {
95 struct ieee80211req_scan_result *isr =
96 (struct ieee80211req_scan_result *) vsr;
98 // determine size of this entry
99 char *id;
100 int idlen;
101 if (isr->isr_meshid_len) {
102 id = vsr + isr->isr_ie_off + isr->isr_ssid_len;
103 idlen = isr->isr_meshid_len;
104 } else {
105 id = vsr + isr->isr_ie_off;
106 idlen = isr->isr_ssid_len;
109 // copy network data
110 char ssid[IEEE80211_NWID_LEN+1];
111 strncpy(ssid, id, idlen);
112 ssid[idlen] = '\0';
113 nsWifiAccessPoint *ap = new nsWifiAccessPoint();
114 ap->setSSID(ssid, strlen(ssid));
115 ap->setMac(isr->isr_bssid);
116 ap->setSignal(isr->isr_rssi);
117 accessPoints.AppendObject(ap);
118 rv = NS_OK;
120 // log the data
121 LOG(( "FreeBSD access point: "
122 "SSID: %s, MAC: %02x-%02x-%02x-%02x-%02x-%02x, "
123 "Strength: %d, Channel: %dMHz\n",
124 ssid, isr->isr_bssid[0], isr->isr_bssid[1], isr->isr_bssid[2],
125 isr->isr_bssid[3], isr->isr_bssid[4], isr->isr_bssid[5],
126 isr->isr_rssi, isr->isr_freq));
128 // increment pointers
129 len -= isr->isr_len;
130 vsr += isr->isr_len;
134 freeifaddrs(ifal);
136 return rv;
139 nsresult
140 nsWifiMonitor::DoScan()
142 // Regularly get the access point data.
144 nsCOMArray<nsWifiAccessPoint> lastAccessPoints;
145 nsCOMArray<nsWifiAccessPoint> accessPoints;
147 do {
148 nsresult rv = FreeBSDGetAccessPointData(accessPoints);
149 if (NS_FAILED(rv))
150 return rv;
152 bool accessPointsChanged = !AccessPointsEqual(accessPoints, lastAccessPoints);
153 ReplaceArray(lastAccessPoints, accessPoints);
155 rv = CallWifiListeners(lastAccessPoints, accessPointsChanged);
156 NS_ENSURE_SUCCESS(rv, rv);
158 // wait for some reasonable amount of time. pref?
159 LOG(("waiting on monitor\n"));
161 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
162 mon.Wait(PR_SecondsToInterval(kDefaultWifiScanInterval));
164 while (mKeepGoing);
166 return NS_OK;