xref: /OK3568_Linux_fs/app/forlinx/flapp/src/plugins/wifi/hostapdcli.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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