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>
15 #include <net/if_media.h>
16 #include <net80211/ieee80211_ioctl.h>
22 #include "nsWifiAccessPoint.h"
24 using namespace mozilla
;
27 FreeBSDGetAccessPointData(nsCOMArray
<nsWifiAccessPoint
> &accessPoints
)
29 // get list of interfaces
31 if (getifaddrs(&ifal
) < 0) {
32 return NS_ERROR_FAILURE
;
37 // loop through the interfaces
38 nsresult rv
= NS_ERROR_FAILURE
;
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
) {
46 // store interface name in socket structure
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);
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) {
69 // check interface is a WiFi interface
70 if (IFM_TYPE(ifmr
.ifm_active
) != IFM_IEEE80211
) {
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) {
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
101 if (isr
->isr_meshid_len
) {
102 id
= vsr
+ isr
->isr_ie_off
+ isr
->isr_ssid_len
;
103 idlen
= isr
->isr_meshid_len
;
105 id
= vsr
+ isr
->isr_ie_off
;
106 idlen
= isr
->isr_ssid_len
;
110 char ssid
[IEEE80211_NWID_LEN
+1];
111 strncpy(ssid
, id
, idlen
);
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
);
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
140 nsWifiMonitor::DoScan()
142 // Regularly get the access point data.
144 nsCOMArray
<nsWifiAccessPoint
> lastAccessPoints
;
145 nsCOMArray
<nsWifiAccessPoint
> accessPoints
;
148 nsresult rv
= FreeBSDGetAccessPointData(accessPoints
);
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
));