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 #include "nsWifiMonitor.h"
6 #include "nsWifiAccessPoint.h"
8 #include "nsServiceManagerUtils.h"
9 #include "nsComponentManagerUtils.h"
10 #include "nsIMutableArray.h"
14 #define DLADM_STRSIZE 256
15 #define DLADM_SECTIONS 3
17 using namespace mozilla
;
19 struct val_strength_t
{
20 const char* strength_name
;
24 static val_strength_t strength_vals
[] = {{"very weak", -112},
30 static nsWifiAccessPoint
* do_parse_str(char* bssid_str
, char* essid_str
,
32 unsigned char mac_as_int
[6] = {0};
33 sscanf(bssid_str
, "%x:%x:%x:%x:%x:%x", &mac_as_int
[0], &mac_as_int
[1],
34 &mac_as_int
[2], &mac_as_int
[3], &mac_as_int
[4], &mac_as_int
[5]);
37 uint32_t strength_vals_count
= sizeof(strength_vals
) / sizeof(val_strength_t
);
38 for (uint32_t i
= 0; i
< strength_vals_count
; i
++) {
39 if (!strncasecmp(strength
, strength_vals
[i
].strength_name
, DLADM_STRSIZE
)) {
40 signal
= strength_vals
[i
].signal_value
;
45 nsWifiAccessPoint
* ap
= new nsWifiAccessPoint();
47 ap
->setMac(mac_as_int
);
48 ap
->setSignal(signal
);
49 size_t len
= essid_str
? strnlen(essid_str
, DLADM_STRSIZE
) : 0;
50 ap
->setSSID(essid_str
, len
);
55 static void do_dladm(nsCOMArray
<nsWifiAccessPoint
>& accessPoints
) {
56 GError
* err
= nullptr;
60 char* dladm_args
[] = {
61 "/usr/bin/pfexec", "/usr/sbin/dladm", "scan-wifi", "-p", "-o",
62 "BSSID,ESSID,STRENGTH"};
64 gboolean rv
= g_spawn_sync("/", dladm_args
, nullptr, (GSpawnFlags
)0, nullptr,
65 nullptr, &sout
, &serr
, &exit_status
, &err
);
66 if (rv
&& !exit_status
) {
67 char wlan
[DLADM_SECTIONS
][DLADM_STRSIZE
+ 1];
69 uint32_t sout_scan
= 0;
70 uint32_t wlan_put
= 0;
72 nsWifiAccessPoint
* ap
;
75 sout_char
= sout
[sout_scan
++];
78 if (sout_char
!= '\0') {
79 wlan
[section
][wlan_put
++] = sout_char
;
84 if (sout_char
== '\\') {
89 if (sout_char
== ':') {
90 wlan
[section
][wlan_put
] = '\0';
96 if ((sout_char
== '\0') || (sout_char
== '\n')) {
97 wlan
[section
][wlan_put
] = '\0';
98 if (section
== DLADM_SECTIONS
- 1) {
99 ap
= do_parse_str(wlan
[0], wlan
[1], wlan
[2]);
101 accessPoints
.AppendObject(ap
);
109 wlan
[section
][wlan_put
++] = sout_char
;
111 } while ((wlan_put
<= DLADM_STRSIZE
) && (section
< DLADM_SECTIONS
) &&
112 (sout_char
!= '\0'));
119 nsresult
nsWifiMonitor::DoScan() {
120 // Regularly get the access point data.
122 nsCOMArray
<nsWifiAccessPoint
> lastAccessPoints
;
123 nsCOMArray
<nsWifiAccessPoint
> accessPoints
;
126 accessPoints
.Clear();
127 do_dladm(accessPoints
);
129 bool accessPointsChanged
=
130 !AccessPointsEqual(accessPoints
, lastAccessPoints
);
131 ReplaceArray(lastAccessPoints
, accessPoints
);
133 nsresult rv
= CallWifiListeners(lastAccessPoints
, accessPointsChanged
);
134 NS_ENSURE_SUCCESS(rv
, rv
);
136 LOG(("waiting on monitor\n"));
138 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
139 mon
.Wait(PR_SecondsToInterval(kDefaultWifiScanInterval
));