| |
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/. */ |
| |
4 |
| |
5 #include "nsWifiMonitor.h" |
| |
6 #include "nsWifiAccessPoint.h" |
| |
7 |
| |
8 #include "nsServiceManagerUtils.h" |
| |
9 #include "nsComponentManagerUtils.h" |
| |
10 #include "nsIMutableArray.h" |
| |
11 |
| |
12 #include "plstr.h" |
| |
13 #include <glib.h> |
| |
14 |
| |
15 #define DLADM_STRSIZE 256 |
| |
16 #define DLADM_SECTIONS 3 |
| |
17 |
| |
18 using namespace mozilla; |
| |
19 |
| |
20 struct val_strength_t { |
| |
21 const char *strength_name; |
| |
22 int signal_value; |
| |
23 }; |
| |
24 |
| |
25 static val_strength_t strength_vals[] = { |
| |
26 { "very weak", -112 }, |
| |
27 { "weak", -88 }, |
| |
28 { "good", -68 }, |
| |
29 { "very good", -40 }, |
| |
30 { "excellent", -16 } |
| |
31 }; |
| |
32 |
| |
33 static nsWifiAccessPoint * |
| |
34 do_parse_str(char *bssid_str, char *essid_str, char *strength) |
| |
35 { |
| |
36 unsigned char mac_as_int[6] = { 0 }; |
| |
37 sscanf(bssid_str, "%x:%x:%x:%x:%x:%x", &mac_as_int[0], &mac_as_int[1], |
| |
38 &mac_as_int[2], &mac_as_int[3], &mac_as_int[4], &mac_as_int[5]); |
| |
39 |
| |
40 int signal = 0; |
| |
41 uint32_t strength_vals_count = sizeof(strength_vals) / sizeof (val_strength_t); |
| |
42 for (uint32_t i = 0; i < strength_vals_count; i++) { |
| |
43 if (!strncasecmp(strength, strength_vals[i].strength_name, DLADM_STRSIZE)) { |
| |
44 signal = strength_vals[i].signal_value; |
| |
45 break; |
| |
46 } |
| |
47 } |
| |
48 |
| |
49 nsWifiAccessPoint *ap = new nsWifiAccessPoint(); |
| |
50 if (ap) { |
| |
51 ap->setMac(mac_as_int); |
| |
52 ap->setSignal(signal); |
| |
53 ap->setSSID(essid_str, PL_strnlen(essid_str, DLADM_STRSIZE)); |
| |
54 } |
| |
55 return ap; |
| |
56 } |
| |
57 |
| |
58 static void |
| |
59 do_dladm(nsCOMArray<nsWifiAccessPoint> &accessPoints) |
| |
60 { |
| |
61 GError *err = nullptr; |
| |
62 char *sout = nullptr; |
| |
63 char *serr = nullptr; |
| |
64 int exit_status = 0; |
| |
65 char * dladm_args[] = { "/usr/bin/pfexec", "/usr/sbin/dladm", |
| |
66 "scan-wifi", "-p", "-o", "BSSID,ESSID,STRENGTH" }; |
| |
67 |
| |
68 gboolean rv = g_spawn_sync("/", dladm_args, nullptr, (GSpawnFlags)0, nullptr, |
| |
69 nullptr, &sout, &serr, &exit_status, &err); |
| |
70 if (rv && !exit_status) { |
| |
71 char wlan[DLADM_SECTIONS][DLADM_STRSIZE+1]; |
| |
72 uint32_t section = 0; |
| |
73 uint32_t sout_scan = 0; |
| |
74 uint32_t wlan_put = 0; |
| |
75 bool escape = false; |
| |
76 nsWifiAccessPoint* ap; |
| |
77 char sout_char; |
| |
78 do { |
| |
79 sout_char = sout[sout_scan++]; |
| |
80 if (escape) { |
| |
81 escape = false; |
| |
82 if (sout_char != '\0') { |
| |
83 wlan[section][wlan_put++] = sout_char; |
| |
84 continue; |
| |
85 } |
| |
86 } |
| |
87 |
| |
88 if (sout_char =='\\') { |
| |
89 escape = true; |
| |
90 continue; |
| |
91 } |
| |
92 |
| |
93 if (sout_char == ':') { |
| |
94 wlan[section][wlan_put] = '\0'; |
| |
95 section++; |
| |
96 wlan_put = 0; |
| |
97 continue; |
| |
98 } |
| |
99 |
| |
100 if ((sout_char == '\0') || (sout_char == '\n')) { |
| |
101 wlan[section][wlan_put] = '\0'; |
| |
102 if (section == DLADM_SECTIONS - 1) { |
| |
103 ap = do_parse_str(wlan[0], wlan[1], wlan[2]); |
| |
104 if (ap) { |
| |
105 accessPoints.AppendObject(ap); |
| |
106 } |
| |
107 } |
| |
108 section = 0; |
| |
109 wlan_put = 0; |
| |
110 continue; |
| |
111 } |
| |
112 |
| |
113 wlan[section][wlan_put++] = sout_char; |
| |
114 |
| |
115 } while ((wlan_put <= DLADM_STRSIZE) && (section < DLADM_SECTIONS) && |
| |
116 (sout_char != '\0')); |
| |
117 } |
| |
118 |
| |
119 g_free(sout); |
| |
120 g_free(serr); |
| |
121 } |
| |
122 |
| |
123 nsresult |
| |
124 nsWifiMonitor::DoScan() |
| |
125 { |
| |
126 // Regularly get the access point data. |
| |
127 |
| |
128 nsCOMArray<nsWifiAccessPoint> lastAccessPoints; |
| |
129 nsCOMArray<nsWifiAccessPoint> accessPoints; |
| |
130 |
| |
131 while (mKeepGoing) { |
| |
132 |
| |
133 accessPoints.Clear(); |
| |
134 do_dladm(accessPoints); |
| |
135 |
| |
136 bool accessPointsChanged = !AccessPointsEqual(accessPoints, lastAccessPoints); |
| |
137 ReplaceArray(lastAccessPoints, accessPoints); |
| |
138 |
| |
139 nsresult rv = CallWifiListeners(lastAccessPoints, accessPointsChanged); |
| |
140 NS_ENSURE_SUCCESS(rv, rv); |
| |
141 |
| |
142 LOG(("waiting on monitor\n")); |
| |
143 |
| |
144 ReentrantMonitorAutoEnter mon(mReentrantMonitor); |
| |
145 mon.Wait(PR_SecondsToInterval(60)); |
| |
146 } |
| |
147 |
| |
148 return NS_OK; |
| |
149 } |