1 #include "hostapdcli.h"
2 #include "terminal.h"
3 #include <QTimer>
4 #include <QDebug>
5
6 #define AP_INTERFACE "interface=%1\n"
7 #define AP_DRIVER "driver=%1\n"
8 #define AP_SSID "ssid=%1\n"
9 #define AP_CHANNEL "channel=%1\n"
10 #define AP_HW_MODE "hw_mode=%1\n"
11 #define AP_MACADDR_ACL "macaddr_acl="
12 #define AP_IGNORE_BROADCAST_SSID "ignore_broadcast_ssid=%1\n"
13 #define AP_AUTH_ALGS "auth_algs=%1\n"
14 #define AP_WPA "wpa=%1\n"
15 #define AP_WPA_PASSPHRASE "wpa_passphrase=%1\n"
16 #define AP_WPA_KEY_MGMT "wpa_key_mgmt=%1\n"
17 #define AP_WPA_PAIRWISE "wpa_pairwise=%1\n"
18 #define AP_RSN_PAIRWISE "rsn_pairwise=%1\n"
19 #define AP_CTR_INTERFACE "ctrl_interface=%1\n"
20 #define AP_RELOAD "reload\n"
21 #define AP_ALL_STA "all_sta\n"
22
23 class HostapdcliPrivate
24 {
25 public:
HostapdcliPrivate(Hostapdcli * _q)26 HostapdcliPrivate(Hostapdcli *_q):q(_q){}
27 void handAutoMessage(const QByteArray &a);
28 void handCmdMessage(const QByteArray &d);
29 QString get(const QByteArray &a, const QByteArray &start, const QByteArray &end);
30 void pharsAllStaInfo(const QByteArray &a, QList<ScanInfoAp> &infos);
31
32 QString message;
33 QString ssid;
34 QString passphrase;
35 QString driver;
36 QString interface;
37 QString ip;
38 QTimer *timer;
39 Hostapdcli *q;
40 };
41
Hostapdcli(QObject * parent)42 Hostapdcli::Hostapdcli(QObject *parent):QObject(parent),
43 m_d(new HostapdcliPrivate(this))
44 {
45 m_d->timer =new QTimer(this);
46 connect(m_d->timer, &QTimer::timeout, this, [=](){
47 allsta();
48 });
49 m_d->timer->setInterval(2000);
50 }
51
~Hostapdcli()52 Hostapdcli::~Hostapdcli()
53 {
54 delete m_d;
55 }
56
start_hostapd(const QString & ko,const QString & ModuleName,const QString & driverName,const QString & cardName,const QString & ip)57 void Hostapdcli::start_hostapd(const QString &ko, const QString &ModuleName, const QString &driverName, const QString &cardName, const QString &ip)
58 {
59 qDebug()<<"start_hostapd";
60
61 m_d->driver = driverName;
62 m_d->interface = cardName;
63 m_d->ip = ip;
64
65 QString moudleIsExit =QString("lsmod | grep %1 | grep -v grep").arg(ModuleName);
66 if(!Terminal::execCmd(moudleIsExit).contains(ModuleName))
67 {
68 qDebug() << Terminal::execCmd("insmod " + ko);
69 qDebug() << QString("insmod %1").arg(ko);
70 }else{
71 qDebug() << QString("driver: %1 already install").arg(ModuleName);
72 }
73
74 QString defaultConfig = QString(
75 "ctrl_interface=/var/run/hostapd\n"
76 "interface=wlan0\n"
77 "driver=%1\n"
78 "ssid=wifi_test\n"
79 "channel=9\n"
80 "hw_mode=g\n"
81 "macaddr_acl=0\n"
82 "ignore_broadcast_ssid=0\n"
83 "auth_algs=1\n"
84 "wpa=3\n"
85 "wpa_passphrase=12345678\n"
86 "wpa_key_mgmt=WPA-PSK\n"
87 "wpa_pairwise=TKIP\n"
88 "rsn_pairwise=CCMP\n").arg(driverName) ;
89 QString hostapdConf = QString("echo \"%1\" > /etc/hostapd.conf").arg(defaultConfig);
90
91 Terminal::execCmd(hostapdConf);
92
93 auto driveInstallFinish = [=](){
94 Terminal::execCmd("echo 1 > /proc/sys/net/ipv4/ip_forward");
95 Terminal::execCmd("iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE");
96 Terminal::execCmd(QString("ifconfig %1 up").arg(cardName));
97 Terminal::execCmd(QString("ifconfig %1 %2").arg(cardName).arg(ip));
98 QString startSevrverCmd =QString("hostapd /etc/hostapd.conf &");
99 if(!Terminal::execCmd("ps -ef | grep -v grep | grep \"hostapd /etc/hostapd.conf\"").contains("hostapd"))
100 {
101 system(startSevrverCmd.toLatin1().data());
102 qDebug()<<"start :"<< startSevrverCmd;
103 }else{
104 qDebug() <<"hostapd already start!";
105 }
106
107 if(!Terminal::execCmd("ps -ef | grep -v grep | grep dnsmasq").contains("dnsmasq"))
108 {
109 Terminal::execCmd("/etc/init.d/dnsmasq start");
110 }else{
111 qDebug() <<"dnsmasq already start!";
112 }
113
114 };
115
116 ///一秒后在启动服务,应为wifi网卡驱动可能没有安转好.
117 QTimer::singleShot(1000, this, [=](){
118 driveInstallFinish();
119 emit hospapdStartFinish();
120 });
121 }
122
setStart(bool bStart)123 void Hostapdcli::setStart(bool bStart)
124 {
125 if(bStart)
126 {
127 this->start("hostapd_cli");
128 m_d->timer->start();
129 }else{
130 m_d->timer->stop();
131 this->stop();
132 }
133 }
134
stop_hostapd()135 void Hostapdcli::stop_hostapd()
136 {
137 qDebug()<<"stop_hostapd ";
138 Terminal::killProcess("dnsmasq");
139 Terminal::killProcess("hostapd");
140 Terminal::execCmd(QString("ifconfig %1 down").arg(m_d->interface));
141 this->stop();
142 QList<ScanInfoAp> info;
143 emit newStaInfo(info);
144 }
145
setWifiName(const QString & ssid)146 void Hostapdcli::setWifiName(const QString &ssid)
147 {
148 m_d->ssid = ssid;
149 send(QString(AP_SSID).arg(ssid));
150 }
151
setWifiPassword(const QString & passphrase)152 void Hostapdcli::setWifiPassword(const QString &passphrase)
153 {
154 m_d->passphrase = passphrase;
155 send(QString(AP_WPA_PASSPHRASE).arg(passphrase));
156 }
157
setInterface(const QString & interface)158 void Hostapdcli::setInterface(const QString &interface)
159 {
160 m_d->interface = interface;
161 send(QString(AP_INTERFACE).arg(interface));
162 }
163
reload()164 void Hostapdcli::reload()
165 {
166 send(AP_RELOAD);
167 }
168
allsta()169 void Hostapdcli::allsta()
170 {
171 send(AP_ALL_STA);
172 }
173
processMessage(const QString & d)174 void Hostapdcli::processMessage(const QString &d)
175 {
176 m_d->message +=d;
177 char enter ='\n';
178 char end='>';
179
180 QByteArray cmdData;
181 QByteArray rowData;
182
183 char lastChar;
184 for(int i=0; i<m_d->message.size(); i++)
185 {
186 char c = m_d->message.at(i).toLatin1();
187 cmdData +=c;
188 rowData +=c;
189
190 if(c == enter)
191 {
192 m_d->handAutoMessage(rowData);
193 qDebug()<<"+++++++++++++++++"<< rowData;
194 rowData.clear();
195 }
196
197 if(c == end && lastChar == enter)
198 {
199 m_d->handCmdMessage(cmdData);
200 qDebug()<<"#################"<< cmdData;
201 cmdData.clear();
202 }
203 lastChar = c;
204 }
205
206 //保存未处理完消息.
207 m_d->message = cmdData;
208 }
209
handAutoMessage(const QByteArray & a)210 void HostapdcliPrivate::handAutoMessage(const QByteArray &a)
211 {
212 if(a.contains("AP-STA-CONNECTED"))
213 {
214 QString ssid = get(a+"end", "AP-STA-CONNECTED", "end");
215 emit q->lostConnected(ssid);
216 }else if(a.contains("AP-STA-DISCONNECTED"))
217 {
218 QString ssid = get(a+"end", "AP-STA-DISCONNECTED", "end").trimmed();
219
220 qDebug()<<"lose ssid ="<<ssid;
221
222 emit q->lostConnected(ssid);
223 }
224 }
225
handCmdMessage(const QByteArray & d)226 void HostapdcliPrivate::handCmdMessage(const QByteArray &d)
227 {
228 QList<ScanInfoAp> list;
229 pharsAllStaInfo(d, list);
230 if(!list.isEmpty())
231 {
232 emit q->newStaInfo(list);
233 // for(int i=0; i<list.size(); i++)
234 // {
235 // qDebug()<<"**************"<< list[i].ssid;
236 // }
237
238 }
239
240 return;
241 QString cmdHead;
242 QByteArray data;
243 int index =0;
244 for(index =0; index<d.size(); index++){
245 cmdHead+=d[index];
246 if(d[index] == '\n'){
247 data = d.mid(index).trimmed();
248 break;
249 }
250 }
251
252 if(cmdHead.isEmpty())
253 {
254 return;
255 }
256
257 // qDebug()<<"cmdhad ="<<cmdHead ;
258 // qDebug()<<"data ="<< data;
259
260 if(cmdHead.contains(AP_RELOAD))
261 {
262 return;
263 }else if(cmdHead.contains(AP_ALL_STA))
264 {
265 QList<ScanInfoAp> list;
266 pharsAllStaInfo(data, list);
267 emit q->newStaInfo(list);
268 return;
269 }if(cmdHead.contains(QString(AP_INTERFACE).arg(interface)))
270 {
271
272 }else if(cmdHead.contains(QString(AP_DRIVER).arg(driver)))
273 {
274
275 }else if(cmdHead.contains(QString(AP_SSID).arg(ssid)))
276 {
277
278 }else if(cmdHead.contains(QString(AP_WPA_PASSPHRASE).arg(passphrase)))
279 {
280
281 }
282
283 q->reload();
284 }
285
get(const QByteArray & a,const QByteArray & start,const QByteArray & end)286 QString HostapdcliPrivate::get(const QByteArray &a, const QByteArray &start, const QByteArray &end)
287 {
288 //CTRL-EVENT-DISCONNECTED bssid=c2:5a:cd:8c:0f:f4 reason=3 //start ="bssid=" end="reaseo" result ="c2:5a:cd:8c:0f:f4"
289 QByteArray data;
290 QString result;
291 for(int i=0; i<a.size(); i++){
292 data +=a[i];
293 if(data.right(start.size()) == start){
294 data.clear();
295 }else if(data.right(end.size()) == end)
296 {
297 result = data.left(data.size() - end.size());
298 result = result.trimmed();
299 break;
300 }
301 }
302
303 return result;
304 }
305
pharsAllStaInfo(const QByteArray & a,QList<ScanInfoAp> & infos)306 void HostapdcliPrivate::pharsAllStaInfo(const QByteArray &a, QList<ScanInfoAp> &infos)
307 {
308 QList<QByteArray>list = a.split('\n');
309
310 ScanInfoAp ap;
311 foreach (QByteArray row, list) {
312 row +="end";
313 if(row.contains("dot11RSNAStatsSTAAddress"))
314 {
315 ap.ssid = get(row, "dot11RSNAStatsSTAAddress=" , "end");
316 }else if(row.contains("rx_bytes"))
317 {
318 ap.rx_bytes = get(row, "rx_bytes=" , "end");
319 }else if(row.contains("tx_bytes"))
320 {
321 ap.tx_bytes = get(row, "tx_bytes=" , "end");
322 }else if(row.contains("signal"))
323 {
324 ap.signal=get(row, "signal=" , "end").toInt();
325 }else if(row.contains("connected_time"))
326 {
327 ap.connected_time = get(row, "connected_time=" , "end");
328 infos << ap;
329 }
330
331 }
332 // 4c:49:e3:19:65:aa
333 // flags=[AUTH][ASSOC][AUTHORIZED]
334 // aid=0
335 // capability=0x0
336 // listen_interval=0
337 // supported_rates=
338 // timeout_next=NULLFUNC POLL
339 // dot11RSNAStatsSTAAddress=4c:49:e3:19:65:aa
340 // dot11RSNAStatsVersion=1
341 // dot11RSNAStatsSelectedPairwiseCipher=00-0f-ac-4
342 // dot11RSNAStatsTKIPLocalMICFailures=0
343 // dot11RSNAStatsTKIPRemoteMICFailures=0
344 // hostapdWPAPTKState=11
345 // hostapdWPAPTKGroupState=0
346 // rx_packets=160
347 // tx_packets=38
348 // rx_bytes=0
349 // tx_bytes=0
350 // inactive_msec=256
351 // signal=-73
352 // rx_rate_info=0
353 // tx_rate_info=0
354 // connected_time=11
355 // supp_op_classes=515153547374757677787c7d7e7f8082
356 // 92:14:5b:9a:65:cd
357 // flags=[AUTH][ASSOC][AUTHORIZED]
358 // aid=0
359 // capability=0x0
360 // listen_interval=0
361 // supported_rates=
362 // timeout_next=NULLFUNC POLL
363 // dot11RSNAStatsSTAAddress=92:14:5b:9a:65:cd
364 // dot11RSNAStatsVersion=1
365 // dot11RSNAStatsSelectedPairwiseCipher=00-0f-ac-4
366 // dot11RSNAStatsTKIPLocalMICFailures=0
367 // dot11RSNAStatsTKIPRemoteMICFailures=0
368 // hostapdWPAPTKState=11
369 // hostapdWPAPTKGroupState=0
370 // rx_packets=1516
371 // tx_packets=1159
372 // rx_bytes=0
373 // tx_bytes=0
374 // inactive_msec=323
375 // signal=-57
376 // rx_rate_info=0
377 // tx_rate_info=0
378 // connected_time=236
379 }
380