4 namespace libnutwireless
{
9 //Wpa_supplicant control commands:
10 QString
CWpaSupplicantBase::wpaCtrlCommand(QString cmd
= "PING") {
11 //int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
12 // char *reply, size_t *reply_len,
13 // void (*msg_cb)(char *msg, size_t len));
15 //Check if we have a control interface:
16 if (cmd_ctrl
== NULL
|| event_ctrl
== NULL
) {
19 if (!m_wpaConnected
or m_inConnectionPhase
) {
22 //First Check if wpa_supplicant is running:
23 QByteArray
command("PING");
25 size_t reply_len
= sizeof(reply
);
27 int status
= wpa_ctrl_request(cmd_ctrl
, command
.constData(), command
.size(), reply
, &reply_len
,NULL
);
28 if ( (status
!= 0) or (QString::fromUtf8(reply
, reply_len
) != "PONG\n") ) {
29 qDebug() << QString("(status=%2)PING COMMAND RESPONSE: %1").arg(QString::fromUtf8(reply
, reply_len
),QString::number(status
));
30 closeWpa("wpaCtrlCommand/nopong");
34 size_t reply_len
= sizeof(reply
);
36 command
= cmd
.toAscii();
38 status
= wpa_ctrl_request(cmd_ctrl
, command
.constData(), command
.size(), reply
, &reply_len
,NULL
);
40 qDebug() << cmd
+ " : " + QString::fromUtf8(reply
, reply_len
) + " EOC";
42 return QString::fromUtf8(reply
, reply_len
);
52 else { //PING command requested
53 qDebug() << cmd
<< ":" << QString::fromUtf8(reply
, reply_len
) << "EOC";
54 return QString::fromUtf8(reply
, reply_len
);
63 // void CWpaSupplicantBase::printMessage(QString msg) {
64 // if (m_logEnabled) {
65 // emit(message(msg));
71 //Reads messages from wpa_supplicant
72 void CWpaSupplicantBase::readFromWpa(int socket
) {
73 if (socket
== m_wpaFd
) {
75 //check if wpa_supplicant is still running (i.e. file exists)
76 if (! QFile::exists(m_wpaSupplicantPath
)) {
77 closeWpa("readFromWpa/no wpa interface on event");
80 //status: 1 = msg available; 0 = no messages, -1 = error
81 int status
= wpa_ctrl_pending(event_ctrl
);
85 size_t reply_len
= sizeof(reply
);
86 wpa_ctrl_recv(event_ctrl
, reply
, &reply_len
);
87 eventDispatcher(QString::fromUtf8(reply
, reply_len
));
89 else if (-1 == status
) {
90 qWarning() << tr("Error while trying to receive messages from wpa_supplicant");
98 //CTRL-RSP-<field name>-<network id>-<value>
101 CTRL-EVENT-DISCONNECTED
104 void CWpaSupplicantBase::eventDispatcher(Request req
) {
105 if (req
.type
!= REQ_FAIL
) {
109 void CWpaSupplicantBase::eventDispatcher(EventType event
, QString str
) {
110 if (event
== EVENT_CONNECTED
) {
111 emit(connectionStateChanged(true,parseEventNetworkId(str
)));
112 emit(networkListUpdated());
114 else if (event
== EVENT_DISCONNECTED
) {
115 emit(connectionStateChanged(false,parseEventNetworkId(str
)));
117 else if (event
== EVENT_TERMINATING
) {
118 closeWpa("event-dispatcher/wpa-TERMINATING");
121 emit(eventMessage(event
));
125 void CWpaSupplicantBase::eventDispatcher(QString event
) {
126 QStringList str_list
= event
.split('\n',QString::KeepEmptyParts
);
127 InteractiveType type
;
128 foreach(QString str
, str_list
) {
129 type
= parseInteract(str
);
132 eventDispatcher(parseReq(str
));
134 case (INTERACT_EVENT
):
135 eventDispatcher(parseEvent(str
),str
);
145 CWpaSupplicantBase::CWpaSupplicantBase(QObject
* parent
, QString m_ifname
) : QObject(parent
), cmd_ctrl(0), event_ctrl(0), m_wpaSupplicantPath("/var/run/wpa_supplicant/"+m_ifname
), m_wpaFd(-1), m_wextFd(-1), m_eventSn(0), m_connectTimerId(-1), m_wextTimerId(-1), m_scanTimerId(-1), m_wextTimerRate(10000), m_ifname(m_ifname
), m_scanTimeoutCount(0),m_wextPollTimeoutCount(0) {
146 m_wpaConnected
= false;
150 //Workaround as constructor of subclass is not beeing called
151 m_apScanDefault
= -1;
152 qDebug() << (QString("Constructor set ap_scan=%1").arg(QString::number(m_apScanDefault
)));
153 m_lastWasAdHoc
= false;
154 qDebug() << (QString("Constructor set m_lastWasAdHoc=%1").arg((m_lastWasAdHoc
) ? "true" : "false"));
157 connect(QCoreApplication::instance(),SIGNAL(aboutToQuit ()),this,SLOT(detachWpa()));
159 CWpaSupplicantBase::~CWpaSupplicantBase() {
160 closeWpa("destructor");
162 void CWpaSupplicantBase::openWpa(bool) {
163 if (m_connectTimerId
!= -1) {
164 killTimer(m_connectTimerId
);
165 m_connectTimerId
= -1;
167 if (m_wextTimerId
!= -1) {
168 killTimer(m_wextTimerId
);
171 if (m_wpaConnected
) return;
173 //Open wpa_supplicant control interface
174 if (!QFile::exists(m_wpaSupplicantPath
)) {
175 qWarning() << tr("Could not open wpa_supplicant socket: %1").arg(QString::number(m_timerCount
));
176 m_inConnectionPhase
= true;
177 m_connectTimerId
= startTimer(dynamicTimerTime(m_timerCount
));
180 cmd_ctrl
= wpa_ctrl_open(m_wpaSupplicantPath
.toAscii().constData());
181 event_ctrl
= wpa_ctrl_open(m_wpaSupplicantPath
.toAscii().constData());
182 if (cmd_ctrl
== NULL
and event_ctrl
== NULL
) {
183 qWarning() << tr("Could not open wpa_supplicant control interface");
184 m_inConnectionPhase
= true;
185 m_connectTimerId
= startTimer(dynamicTimerTime(m_timerCount
));
188 if (cmd_ctrl
== NULL
) {
189 wpa_ctrl_close(event_ctrl
);
191 qWarning() << tr("Could not open wpa_supplicant control interface");
192 m_inConnectionPhase
= true;
193 m_connectTimerId
= startTimer(dynamicTimerTime(m_timerCount
));
196 if (event_ctrl
== NULL
) {
197 wpa_ctrl_close(cmd_ctrl
);
199 qWarning() << tr("Could not open wpa_supplicant control interface");
200 m_inConnectionPhase
= true;
201 m_connectTimerId
= startTimer(dynamicTimerTime(m_timerCount
));
205 //Atach event monitor
206 status
= wpa_ctrl_attach(event_ctrl
);
207 //Status : 0 = succ; -1 = fail, -2 = timeout
209 wpa_ctrl_close(event_ctrl
);
210 wpa_ctrl_close(cmd_ctrl
);
213 qWarning() << tr("Could not attach to wpa_supplicant");
214 m_inConnectionPhase
= true;
215 m_connectTimerId
= startTimer(dynamicTimerTime(m_timerCount
));
218 m_inConnectionPhase
= false;
220 //Set socket notifier
221 m_wpaFd
= wpa_ctrl_get_fd(event_ctrl
);
222 m_eventSn
= new QSocketNotifier(m_wpaFd
, QSocketNotifier::Read
,NULL
);
223 connect(m_eventSn
,SIGNAL(activated(int)),this,SLOT(readFromWpa(int)));
224 m_eventSn
->setEnabled(true);
225 m_wpaConnected
= true;
227 //NEW FEATURE: Signal level retrieving:
229 //Get file Descriptor to NET kernel
230 if ( (m_wextFd
= iw_sockets_open()) < 0) {
232 qWarning() << tr("ERROR: Could not open socket to net kernel");
234 else { //Socket is set up, now set SocketNotifier
235 qDebug() << QString("File Descriptor for Wext is: %1").arg(QString::number(m_wextFd
));
238 //Start timer for reading wireless info (like in /proc/net/wireless)
239 m_wextTimerId
= startTimer(m_wextTimerRate
);
241 //Set ap_scan default
244 //Continue of old features:
245 emit(stateChanged(true));
246 printMessage(tr("wpa_supplicant connection established"));
250 bool CWpaSupplicantBase::closeWpa(QString call_func
, bool internal
) {
251 if (m_connectTimerId
!= -1) {
252 killTimer(m_connectTimerId
);
253 m_connectTimerId
= -1;
254 m_inConnectionPhase
= false;
257 if (m_wextTimerId
!= -1) {
258 killTimer(m_wextTimerId
);
261 if (m_wpaConnected
) {
262 if (m_eventSn
!= NULL
) {
263 disconnect(m_eventSn
,SIGNAL(activated(int)),this,SLOT(readFromWpa(int)));
267 if (-1 != m_wextFd
) {
268 iw_sockets_close(m_wextFd
);
271 //Detaching takes place if program is about to quit
272 //Close control connections
273 wpa_ctrl_close(event_ctrl
);
274 wpa_ctrl_close(cmd_ctrl
);
277 m_wpaConnected
= false;
278 emit(stateChanged(false));
280 printMessage(tr("(%1)[%2] wpa_supplicant disconnected").arg(((internal
) ? "internal" : "external"),call_func
));
283 int CWpaSupplicantBase::dynamicTimerTime(int m_timerCount
) {
284 if (m_timerCount
> 0) {
285 if (m_timerCount
<= 5) {
288 if (m_timerCount
<= 10) {
291 if (m_timerCount
<= 15) {
302 //Slot is executed when aplication is about to quit;
303 void CWpaSupplicantBase::detachWpa() {
304 if (event_ctrl
!= NULL
) {
305 wpa_ctrl_detach(event_ctrl
);
309 void CWpaSupplicantBase::setScanResults(QList
<WextRawScan
> wextScanResults
) {
310 QString response
= wpaCtrlCmd_SCAN_RESULTS();
311 if (response
.isEmpty()) {
312 m_wpaScanResults
= QList
<ScanResult
>();
316 //Set scan results from wpa_supplicant:
317 m_wpaScanResults
= parseScanResult(sliceMessage(response
));
318 //This may not be possible as qHash references an namespace that is unknown to qt TODO:CHECK!
319 QHash
<QString
,WextScan
> wextScanHash
; //Namespace problem
321 foreach(WextRawScan i
, wextScanResults
) {
322 wextScan
.ssid
= i
.ssid
;
323 wextScan
.bssid
= i
.bssid
;
324 wextScan
.signal
= convertValues(i
);
325 wextScan
.hasRange
= i
.hasRange
;
326 wextScan
.we_version_compiled
= i
.we_version_compiled
;
327 wextScan
.freq
= i
.freq
;
328 wextScan
.group
= i
.group
;
329 wextScan
.pairwise
= i
.pairwise
;
330 wextScan
.keyManagement
= i
.keyManagement
;
331 wextScan
.protocols
= i
.protocols
;
332 wextScan
.opmode
= i
.opmode
;
333 wextScan
.bitrates
= i
.bitrates
;
334 wextScanHash
.insert(i
.bssid
.toString(), wextScan
);
338 QHash
<QString
,WextScan
>::iterator wextScanHashIter
;
339 //Set the signal quality and so on
340 for (QList
<ScanResult
>::Iterator i
= m_wpaScanResults
.begin(); i
!= m_wpaScanResults
.end(); ++i
) {
341 if (wextScanHash
.contains(i
->bssid
.toString())) { //We do have this network in our wext list
342 wextScanHashIter
= wextScanHash
.find(i
->bssid
.toString());
343 //Workaround for some cards that send wrong information via wext.
344 //If ssid is hidden (empty), then we do not set the information from the wext.
345 i
->bssid
= wextScanHashIter
.value().bssid
;
346 if (!wextScanHashIter
.value().ssid
.isEmpty() && i
->ssid
.isEmpty()) {
347 i
->ssid
= "<hidden>";
349 else if (!wextScanHashIter
.value().ssid
.isEmpty()) {
350 i
->ssid
= wextScanHashIter
.value().ssid
;
352 if (-1 != frequencyToChannel(wextScanHashIter
.value().freq
)) {
353 i
->freq
= wextScanHashIter
.value().freq
;
355 i
->signal
= wextScanHashIter
.value().signal
;
356 i
->group
= wextScanHashIter
.value().group
;
357 i
->pairwise
= wextScanHashIter
.value().pairwise
;
358 i
->keyManagement
= wextScanHashIter
.value().keyManagement
;
359 i
->protocols
= wextScanHashIter
.value().protocols
;
360 i
->opmode
= wextScanHashIter
.value().opmode
;
361 i
->bitrates
= wextScanHashIter
.value().bitrates
;
362 wextScanHash
.erase(wextScanHashIter
);
365 else { //Network is unknown to wext, add level type information
366 if (m_signalQuality
.type
!= WSR_UNKNOWN
) {
367 i
->signal
.type
= m_signalQuality
.type
;
371 ScanResult scanresult
;
372 //Now add all remaining networks:
373 for(QHash
<QString
,WextScan
>::iterator i
= wextScanHash
.begin(); i
!= wextScanHash
.end(); ++i
) {
374 scanresult
.bssid
= i
.value().bssid
;
375 scanresult
.ssid
= i
.value().ssid
;
376 scanresult
.freq
= i
.value().freq
;
377 scanresult
.signal
= i
.value().signal
;
378 scanresult
.group
= i
.value().group
;
379 scanresult
.pairwise
= i
.value().pairwise
;
380 scanresult
.keyManagement
= i
.value().keyManagement
;
381 scanresult
.protocols
= i
.value().protocols
;
382 scanresult
.opmode
= i
.value().opmode
;
383 scanresult
.bitrates
= i
.value().bitrates
;
384 m_wpaScanResults
.append(scanresult
);
387 qDebug() << "Found " << count
<< "BSSIDs; " << wextScanHash
.size() << " in Hash; " << m_wpaScanResults
.size() << " in wpa_supplicant list";
388 //The complete list is done;
389 emit(scanCompleted());
395 void CWpaSupplicantBase::timerEvent(QTimerEvent
*event
) {
396 if (event
->timerId() == m_wextTimerId
) {
397 if ( (m_wextFd
!= -1) && m_wpaConnected
) {
401 else if (event
->timerId() == m_connectTimerId
) {
402 if (!m_wpaConnected
) {
406 killTimer(m_connectTimerId
);
407 m_connectTimerId
= -1;
411 else if (event
->timerId() == m_scanTimerId
) {
412 if ( (m_wextFd
!= -1) && m_wpaConnected
) {
418 bool CWpaSupplicantBase::connected() {
419 if (wpaCtrlCmd_PING() == "PONG\n") {
430 void CWpaSupplicantBase::setSignalQualityPollRate(int msec
) {
431 m_wextPollTimeoutCount
= 0;
432 if (m_wextTimerId
!= -1) {
433 qDebug() << "Setting signal quality polling (restarting timer)";
434 killTimer(m_wextTimerId
);
435 m_wextTimerRate
= msec
;
436 m_wextTimerId
= startTimer(m_wextTimerRate
);
439 qDebug() << "Setting signal quality polling (starting timer)";
440 m_wextTimerRate
= msec
;
441 m_wextTimerId
= startTimer(m_wextTimerRate
);
444 int CWpaSupplicantBase::getSignalQualityPollRate() {
445 return m_wextTimerRate
;
447 WextSignal
CWpaSupplicantBase::getSignalQuality() {
448 return m_signalQuality
;
451 void CWpaSupplicantBase::setLog(bool enabled
) {
452 m_logEnabled
= enabled
;
456 void CWpaSupplicantBase::scan() {
457 if (0 == wpaCtrlCmd_SCAN().indexOf("OK")) {
458 //Check if we're already scanning:
459 if (m_scanTimerId
!= -1) {
460 killTimer(m_scanTimerId
);
462 printMessage("We're already scanning!");
464 //Return scanresults from wpa_supplicant immediately
465 setScanResults(QList
<WextRawScan
>());
466 m_scanTimeoutCount
= 0;
467 m_scanTimerId
= startTimer(CWPA_SCAN_TIMER_TIME
);
472 //noise levels, returned by this functions, are invalid, don't use them
473 void CWpaSupplicantBase::tryScanResults() {
474 if (m_wextFd
== -1 || !m_wpaConnected
) {
478 if (m_scanTimerId
!= -1) {
479 killTimer(m_scanTimerId
);
482 else { //This is not a timer call; this should not happen
483 qWarning() << tr("Warning, no timer present while trying to get scan results");
487 memset(&wrq
,0,sizeof(struct iwreq
));
488 unsigned char * buffer
= NULL
; /* Results */
489 int buflen
= IW_SCAN_MAX_DATA
; /* Min for compat WE<17 */
490 struct iw_range range
;
491 memset(&range
,0,sizeof(struct iw_range
));
493 QList
<WextRawScan
> res
= QList
<WextRawScan
>();
494 WextRawScan singleres
;
495 singleres
.bssid
= libnutcommon::MacAddress();
496 singleres
.group
= GCI_UNDEFINED
;
497 singleres
.pairwise
= PCI_UNDEFINED
;
498 singleres
.protocols
= PROTO_UNDEFINED
;
499 singleres
.keyManagement
= KM_UNDEFINED
;
502 struct wireless_config wifiConfig
;
503 memset(&wifiConfig
,0,sizeof(struct wireless_config
));
505 /* Get basic information */
506 if(iw_get_basic_config(m_wextFd
, m_ifname
.toAscii().constData(), &wifiConfig
) < 0) {
507 /* If no wireless name : no wireless extensions */
508 /* But let's check if the interface exists at all */
510 memset(&ifr
,0,sizeof(struct ifreq
));
512 strncpy(ifr
.ifr_name
, m_ifname
.toAscii().data(), IFNAMSIZ
);
513 if(ioctl(m_wextFd
, SIOCGIFFLAGS
, &ifr
) < 0)
514 qWarning() << tr("(Wireless Extension) No device present");
516 qWarning() << tr("(Wireless Extension) Device not supported");
519 qDebug() << "Fetched basic config.";
522 if(iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWAP
, &wrq
) >= 0) {
523 qDebug() << "Got AP";
527 if(iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWRATE
, &wrq
) >= 0) {
528 qDebug() << "Got bit rate";
531 /* Get Power Management settings */
532 wrq
.u
.power
.flags
= 0;
533 if(iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWPOWER
, &wrq
) >= 0) {
534 qDebug() << "Got power";
538 /* Get range stuff */
539 /* Get range stuff */
540 qDebug() << QString("Getting range stuff for %1").arg(m_ifname
.toAscii().data());
541 if (iw_get_range_info(m_wextFd
, m_ifname
.toAscii().data(), &range
) >= 0) {
543 qDebug() << "Success readWirelessInfo getrange" << strerror(errno
);
545 else { //This is VERY strange: we always get the "operation not permitted" error, although iw_get_range() worked
546 qDebug() << QString("Error \"hasRange == 0\" (%1)").arg(strerror(errno
));
548 singleres
.hasRange
= has_range
;
550 //If we get a timeout for more than 5 times, stop polling.
551 if (errno
== EAGAIN
) {
552 qDebug() << "Scan results not available yet";
553 m_scanTimeoutCount
++;
554 if (m_scanTimeoutCount
== 5) {
557 m_scanTimerId
= startTimer(CWPA_SCAN_RETRY_TIMER_TIME
);
561 qDebug() << "Got range stuff";
564 singleres
.maxquality
.level
= (quint8
) range
.max_qual
.level
;
565 singleres
.maxquality
.qual
= (quint8
) range
.max_qual
.qual
;
566 singleres
.maxquality
.noise
= (quint8
) range
.max_qual
.noise
;
567 singleres
.maxquality
.updated
= (quint8
) range
.max_qual
.updated
;
568 qDebug() << "RANGE (scanresults): " << singleres
.maxquality
.level
<< singleres
.maxquality
.qual
<< singleres
.maxquality
.noise
<< singleres
.maxquality
.updated
;
571 singleres
.maxquality
.level
= 0;
572 singleres
.maxquality
.qual
= 0;
573 singleres
.maxquality
.noise
= 0;
574 singleres
.maxquality
.updated
= 0;
575 qWarning() << tr("Range information are not available");
578 unsigned char * newbuf
;
579 for (int i
=0; i
<= 16; i
++) { //realloc (don't do this forever)
581 newbuf
= (uchar
*) realloc(buffer
, buflen
);
587 qDebug() << "Allocating buffer for Wext failed";
592 //Set Request variables:
593 wrq
.u
.data
.pointer
= buffer
;
594 wrq
.u
.data
.flags
= 0;
595 wrq
.u
.data
.length
= buflen
;
598 if (iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWSCAN
, &wrq
) < 0) {
599 //Buffer is too small
600 if((errno
== E2BIG
) && (range
.we_version_compiled
> 16)) {
602 //check if driver gives any hints about scan length:
603 if (wrq
.u
.data
.length
> buflen
) {
604 buflen
= wrq
.u
.data
.length
;
606 else { //If not, double the length
609 //Start from the beginning:
610 qDebug() << "Buffer was too small";
613 //No range error occured or kernel has wireless extension < 16
614 if (errno
== EAGAIN
) {
615 qDebug() << "Scan results not available yet";
616 m_scanTimerId
= startTimer(CWPA_SCAN_RETRY_TIMER_TIME
);
625 qWarning() << tr("(%1) Failed to read scan data : %2").arg(m_ifname
, QString(strerror(errno
)));
627 else { //Results are there
633 if (wrq
.u
.data
.length
) {
636 memset(&iwe
,0,sizeof(struct iw_event
));
637 struct stream_descr stream
;
638 memset(&stream
,0,sizeof(struct stream_descr
));
644 libnutcommon::MacAddress tmpMac
;
645 iw_init_event_stream(&stream
, (char *) buffer
, wrq
.u
.data
.length
);
647 /* Extract an event and parse it*/
648 memset(&iwe
,0,sizeof(struct iw_event
)); //valgrind complains about it?
649 ret
= iw_extract_event_stream(&stream
, &iwe
, range
.we_version_compiled
);
651 //Now parse our scan event:
654 //ap_addr has type socketaddr
655 //Workaround for macaddress
656 iw_saether_ntop(&(iwe
.u
.ap_addr
), buffer2
);
657 tmpMac
= libnutcommon::MacAddress(QString::fromAscii(buffer2
,128));
659 if (singleres
.bssid
.zero()) { //First bssid
660 singleres
.bssid
= tmpMac
;
661 qDebug() << "Start parsing one network" << singleres
.bssid
.toString();
663 // if our last bssid is different from the actual one, then we have to append it to our scanlist
664 if ( (singleres
.bssid
!= tmpMac
) ) {
665 res
.append(singleres
);
666 qDebug() << "End parsing one network" << singleres
.bssid
.toString();
668 singleres
.ssid
= QString();
669 singleres
.bssid
.clear();
670 singleres
.quality
= WextRawSignal();
672 singleres
.group
= GCI_UNDEFINED
;
673 singleres
.pairwise
= PCI_UNDEFINED
;
674 singleres
.keyManagement
= KM_UNDEFINED
;
675 singleres
.protocols
= PROTO_UNDEFINED
;
676 singleres
.opmode
= OPM_AUTO
;
677 singleres
.bssid
= tmpMac
;
678 qDebug() << "Start parsing one network" << singleres
.bssid
.toString();
680 qDebug() << "BSSID" << singleres
.bssid
.toString();
682 case IWEVQUAL
: //Quality event:
683 qDebug() << "Quality" << singleres
.bssid
.toString();
684 singleres
.quality
.qual
= (quint8
) iwe
.u
.qual
.qual
;
685 singleres
.quality
.level
= (quint8
) iwe
.u
.qual
.level
;
686 singleres
.quality
.noise
= (quint8
) iwe
.u
.qual
.noise
;
687 singleres
.quality
.updated
= (quint8
) iwe
.u
.qual
.updated
;
688 qDebug() << "STATS (scanresults): " << singleres
.quality
.level
<< singleres
.quality
.qual
<< singleres
.quality
.noise
<< singleres
.quality
.updated
;
691 qDebug() << "Frequency" << singleres
.bssid
.toString();
694 freq
= iw_freq2float(&(iwe
.u
.freq
)); //Hopefully in hz
695 if ( ( (freq
/1e9
) < 10.0 ) && ( (freq
/1e9
) > 0.0 ) ) {
696 singleres
.freq
= (int) (freq
/1e6
);
697 qDebug() << "Channel for" << singleres
.ssid
<< "is " << freq
<< singleres
.freq
;
706 qDebug() << "Mode:" << singleres
.bssid
.toString();
707 if(iwe
.u
.mode
>= IW_NUM_OPER_MODE
) {
708 iwe
.u
.mode
= IW_NUM_OPER_MODE
;
710 singleres
.opmode
= (OPMODE
) iwe
.u
.mode
;
713 qDebug() << "ESSID:" << singleres
.bssid
.toString();
714 if (iwe
.u
.essid
.flags
) {
715 /* Does it have an ESSID index ? */
716 if ( iwe
.u
.essid
.pointer
&& iwe
.u
.essid
.length
) {
717 if ( (iwe
.u
.essid
.flags
& IW_ENCODE_INDEX
) > 1) {
718 singleres
.ssid
= QString("%1 [%2]").arg(QString::fromAscii((char*) iwe
.u
.essid
.pointer
,iwe
.u
.essid
.length
), QString::number(iwe
.u
.essid
.flags
& IW_ENCODE_INDEX
));
721 singleres
.ssid
= QString("%1").arg(QString::fromAscii((char*) iwe
.u
.essid
.pointer
,iwe
.u
.essid
.length
));
725 singleres
.ssid
= QString("N/A");
728 else { //Hidden essid or broken driver
729 singleres
.ssid
= QString();
733 case SIOCGIWENCODE
: //Get encrytion stuff: (just the key)
734 qDebug() << "Encode" << singleres
.bssid
.toString();
735 if (! iwe
.u
.data
.pointer
) {
736 iwe
.u
.data
.flags
|= IW_ENCODE_NOKEY
;
738 if(iwe
.u
.data
.flags
& IW_ENCODE_DISABLED
) { //Encryption is disabled
739 singleres
.keyManagement
= KM_OFF
;
740 qDebug() << "PARING ENCODE-Information: NO KEY";
743 //Extract key information: (See iwlib.c line 1500)
745 //keyflags: iwe.u.data.flags
746 //keysize = iwe.u.data.length
749 if (iwe
.u
.data
.flags
& IW_ENCODE_NOKEY
) { //no key
750 if (iwe
.u
.data
.length
<= 0) {
751 //Encryption is on, but group is unknown
752 singleres
.keyManagement
= KM_NONE
;
753 qDebug() << "PARSING ENCODE-INFORMATION: WEP KEY";
755 } //else: we have a, key but check type later
760 singleres
.bitrates
.append((qint32
) iwe
.u
.bitrate
.value
);
761 qDebug() << "Adding Bitrate: " << (qint32
) iwe
.u
.bitrate
.value
;
764 case IWEVGENIE
: //group/pairwsie ciphers etc.
765 //buffer = iwe.u.data.pointer
766 //bufflen = iwe.u.data.length
767 qDebug() << "IE_START" << singleres
.bssid
.toString();
770 /* Loop on each IE, each IE is minimum 2 bytes */
771 while(offset
<= (iwe
.u
.data
.length
- 2)) {
773 if (0xdd == ((uchar
*) iwe
.u
.data
.pointer
)[offset
] || (0x30 == ((uchar
*) iwe
.u
.data
.pointer
)[offset
]) ) { // WPA1/2
774 parseWextIeWpa(((uchar
*) iwe
.u
.data
.pointer
) + offset
, iwe
.u
.data
.length
, &singleres
);
776 qDebug() << "Parsed IE-Information of " << singleres
.ssid
<< singleres
.bssid
.toString();
777 qDebug() << toString(singleres
.group
) << toString(singleres
.pairwise
) << toString(singleres
.keyManagement
);
779 /* Skip over this IE to the next one in the list. */
780 offset
+= buffer
[offset
+1] + 2;
783 qDebug() << "IE_END" << singleres
.bssid
.toString();
786 default: //Ignore all other event types. Maybe we need them later?
790 else { //Append last scan:
791 if (!singleres
.bssid
.zero()) {
792 res
.append(singleres
);
793 qDebug() << "End parsing one network" << singleres
.bssid
.toString();
804 //We have the data, now construct complete ScanResult
808 qWarning() << tr("No Scanresults available");
816 void CWpaSupplicantBase::readWirelessInfo() {
817 qDebug() << "Executing readWirelessInfo() with TimerRate of" << m_wextTimerRate
;
818 if ( (m_wextFd
== -1) || !m_wpaConnected
) {
821 struct iw_range range
;
822 memset(&range
,0,sizeof(struct iw_range
));
825 memset(&stats
,0,sizeof(iwstats
));
828 struct wireless_config wifiConfig
;
829 memset(&wifiConfig
,0,sizeof(struct wireless_config
));
830 /* Get basic information */
831 if(iw_get_basic_config(m_wextFd
, m_ifname
.toAscii().constData(), &wifiConfig
) < 0) {
832 /* If no wireless name : no wireless extensions */
833 /* But let's check if the interface exists at all */
835 memset(&ifr
,0,sizeof(struct ifreq
));
837 strncpy(ifr
.ifr_name
, m_ifname
.toAscii().data(), IFNAMSIZ
);
838 if(ioctl(m_wextFd
, SIOCGIFFLAGS
, &ifr
) < 0)
839 qWarning() << tr("(Wireless Extension) No device present");
841 qWarning() << tr("(Wireless Extension) device not supported");
844 qDebug() << "Fetched basic config.";
846 //We encode frequency in mhz;
847 //kernel encodes as double; (hopefully always in hz)
848 //But better test this:
850 if (wifiConfig
.has_freq
) {
851 if ( ( (wifiConfig
.freq
/1e9
) < 10.0 ) && ( (wifiConfig
.freq
/1e9
) > 0.0 ) ) {
852 res
.freq
= (int) (wifiConfig
.freq
/1e6
);
857 memset(&wrq
,0,sizeof(struct iwreq
));
860 if(iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWAP
, &wrq
) >= 0) {
861 //Add mac address of current ap;
863 iw_saether_ntop(&(wrq
.u
.ap_addr
), buffer
);
864 res
.bssid
= libnutcommon::MacAddress(QString::fromAscii(buffer
,128));
865 qDebug() << "Got AP: " << res
.bssid
.toString();
869 quint8
* buffer
= new quint8
[IW_ESSID_MAX_SIZE
];
870 memset(buffer
, '\0', IW_ESSID_MAX_SIZE
);
871 wrq
.u
.essid
.pointer
= (void *)buffer
;
872 wrq
.u
.essid
.length
= IW_ESSID_MAX_SIZE
;
873 if(iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWESSID
, &wrq
) >= 0) {
874 if (wrq
.u
.essid
.length
> IW_ESSID_MAX_SIZE
)
875 wrq
.u
.essid
.length
= IW_ESSID_MAX_SIZE
;
876 if (wrq
.u
.essid
.flags
) {
877 /* Does it have an ESSID index ? */
878 if ( wrq
.u
.essid
.pointer
&& wrq
.u
.essid
.length
) {
879 if ( (wrq
.u
.essid
.flags
& IW_ENCODE_INDEX
) > 1) {
880 res
.ssid
= QString("%1 [%2]").arg(QString::fromAscii((char*) wrq
.u
.essid
.pointer
, wrq
.u
.essid
.length
), QString::number(wrq
.u
.essid
.flags
& IW_ENCODE_INDEX
));
883 res
.ssid
= QString::fromAscii((char*) wrq
.u
.essid
.pointer
, wrq
.u
.essid
.length
);
890 qDebug() << "Got ssid: " << res
.ssid
;
895 if(iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWRATE
, &wrq
) >= 0) {
896 res
.bitrates
.append((qint32
) wrq
.u
.bitrate
.value
);
897 qDebug() << "Got bit rate: " << res
.bitrates
[0];
900 /* Get Power Management settings */
901 wrq
.u
.power
.flags
= 0;
902 if(iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWPOWER
, &wrq
) >= 0) {
903 qDebug() << "Got power";
908 /* Get range stuff */
909 qDebug() << QString("Getting range stuff for %1").arg(m_ifname
.toAscii().data());
910 if (iw_get_range_info(m_wextFd
, m_ifname
.toAscii().data(), &range
) >= 0) {
912 qDebug() << "Success readWirelessInfo getrange" << strerror(errno
);
914 else { //This is VERY strange: we always get the "operation not permitted" error, although iw_get_range() worked
915 qDebug() << QString("Error \"hasRange == 0\" (%1)").arg(strerror(errno
));
917 res
.hasRange
= hasRange
;
918 if (errno
== EAGAIN
) {
919 m_wextPollTimeoutCount
++;
920 qDebug() << QString("Getting range stuff failed (%1)").arg(strerror(errno
));
921 if ( (m_wextPollTimeoutCount
> 10) && m_wextTimerRate
< 1000) {
922 setSignalQualityPollRate(10000);
924 else if (m_wextPollTimeoutCount
> 10) { //Fast polling disabled, but still EAGAIN errors
925 //Seems the kernel does not care about our calls
926 killTimer(m_wextTimerId
);
932 qDebug() << "Got range stuff";
935 //Set supported Frequencies if the list is not empty;
936 if (m_supportedFrequencies
.isEmpty() && hasRange
) {
937 qDebug() << range
.num_frequency
;
938 qDebug() << "Printing Frequency information";
942 for (int i
=0; i
< range
.num_channels
; i
++) {
943 m
= (quint32
) range
.freq
[i
].m
;
944 e
= (quint16
) range
.freq
[i
].e
;
946 for (int j
=0; j
< 9-e
-3; j
++) {
947 freqinmhz
= freqinmhz
/10;
949 if (!m_supportedFrequencies
.contains(freqinmhz
)) { //Only add frequency that are not in our list
950 m_supportedFrequencies
.append(freqinmhz
);
952 qDebug() << m
<< e
<< freqinmhz
<< frequencyToChannel(freqinmhz
);
954 qDebug() << "Done printing";
957 qDebug() << "m_supportedFrequencies not set";
961 res
.maxquality
.level
= (quint8
) range
.max_qual
.level
;
962 res
.maxquality
.qual
= (quint8
) range
.max_qual
.qual
;
963 res
.maxquality
.noise
= (quint8
) range
.max_qual
.noise
;
964 res
.maxquality
.updated
= (quint8
) range
.max_qual
.updated
;
965 qDebug() << "RANGE: " << res
.maxquality
.level
<< res
.maxquality
.qual
<< res
.maxquality
.noise
<< res
.maxquality
.updated
;
968 res
.maxquality
.level
= 0;
969 res
.maxquality
.qual
= 0;
970 res
.maxquality
.noise
= 0;
971 res
.maxquality
.updated
= 0;
972 qDebug() << "Range information are not available";
974 if ( (hasRange
) && (range
.we_version_compiled
> 11) ) {
976 memset(&wrq
,0,sizeof(struct iwreq
));
977 wrq
.u
.data
.pointer
= (caddr_t
) &stats
;
978 wrq
.u
.data
.length
= sizeof(struct iw_statistics
);
979 wrq
.u
.data
.flags
= 1; // Clear updated flag
980 strncpy(wrq
.ifr_name
, m_ifname
.toAscii().data(), IFNAMSIZ
);
982 qDebug() << "Getting wireless stats";
983 if(iw_get_ext(m_wextFd
, m_ifname
.toAscii().data(), SIOCGIWSTATS
, &wrq
) < 0) {
984 qWarning() << tr("Error occured while fetching wireless info: ") << strerror(errno
);
986 else { //Stats fetched
987 qDebug() << "Stats fetched";
988 res
.quality
.level
= (quint8
) stats
.qual
.level
;
989 res
.quality
.qual
= (quint8
) stats
.qual
.qual
;
990 res
.quality
.noise
= (quint8
) stats
.qual
.noise
;
991 res
.quality
.updated
= (quint8
) stats
.qual
.updated
;
992 qDebug() << "STATS: " << res
.quality
.level
<< res
.quality
.qual
<< res
.quality
.noise
<< res
.quality
.updated
;
993 m_signalQuality
= convertValues(res
);
994 qDebug() << "Emittig m_signalQualityUpdated()";
995 if (m_wextTimerRate
< 1000) {
996 setSignalQualityPollRate(10000);
997 printMessage(tr("Auto-resetting timer to 10 seconds"));
999 emit
signalQualityUpdated(m_signalQuality
);
1002 else if (range
.we_version_compiled
<= 11) {
1003 printMessage(tr("Cannot fetch wireless information as your wireless extension is too old"));
1004 printMessage(tr("Think about updating your kernel (it's way too old)"));
1007 qDebug() << "Error while trying to fetch wireless information" << strerror(errno
);
1008 qDebug() << "Wireless Extension socket file descriptor was: " << m_wextFd
;
1013 QList
<ScanResult
> CWpaSupplicantBase::scanResults() {
1014 return m_wpaScanResults
;