KernelPanic KernelPanic - 1 month ago 8
Linux Question

SIOCGIWFREQ ioctl returning error 22 EINVAL - Invalid argument, why?

I am struggling to read current frequency channel of Wifi card using Wireless Extension Tools for Linux library with following

Qt/C++
method:

const UeTypeCurrentFrequencyChannel& UeNetworkManager::ueCurrentFrequencyChannel(const QString& interfaceName)
{
static UeTypeCurrentFrequencyChannel result=UeTypeCurrentFrequencyChannel();
iwreq wrq;
iw_range range;
int kernelSocket=iw_sockets_open();

if(iw_get_range_info(kernelSocket,
interfaceName.toLocal8Bit().constData(),
&range)>=0)
{
if(iw_get_ext(kernelSocket,
interfaceName.toLocal8Bit().constData(),
SIOCGIWFREQ,
&wrq)>=0)
{
//BUG current frequency and channel is not read, it might be becuase of nonroot credentials - it returns error 22 (EINVAL - Invalid argument), why?
result.first=iw_freq2float(&(wrq.u.freq));
result.second=iw_freq_to_channel(result.first.toDouble(),
&range);

qDebug() << Q_FUNC_INFO
<< "success - current channel:"
<< result;
}
else
{
result.first=QString(interfaceName);
result.second=QString(tr("current channel read failed."));

qDebug() << Q_FUNC_INFO
<< "error (iw_get_ext):"
<< errno;
} // if
}
else
{
result.first=QString(interfaceName);
result.second=QString(tr("current channel read failed."));

qDebug() << Q_FUNC_INFO
<< "error (iw_get_range_info):"
<< errno;
} // if

iw_sockets_close(kernelSocket);

return result;
} // ueCurrentFrequencyChannel


Now,
iw_get_ext
always returns
-1
and
errno
is set to value of
22
. I've taken a look at the errno.h and search for error
22
and I've got following error declaration:

#define EINVAL 22 /* Invalid argument */
.

Why am I getting
Invalid argument
error while trying to query current frequency channel of network adapter with
ioctl
? I've launched application containing this code as normal user and as root, same result any time:

static const UeTypeCurrentFrequencyChannel& UeNetworkManager::ueCurrentFrequencyChannel(const QString&) error(iw_get_ext): 22


Why, what am I missing?

Addendum #1:

If I scan WiFi cards and networks using
iwlist
from terminal, I get all needed info, regardless if I run it as normal user or root.

Addendum #2:
The code has been upgraded,
iw_get_range_info()
works.

Addendum #3:
The situation have just got weired; On random occasions, I get succes:

static const UeTypeCurrentFrequencyChannel& UeNetworkManager::ueCurrentFrequencyChannel(const QString&) success - current channel: QPair(QVariant(double, 2.412e+09),QVariant(int, 1))


which same as
iwlist scan output
:

wlan0 Scan completed :
Cell 01 - Address: 64:6E:EA:22:21:D4
Channel:1
Frequency:2.412 GHz (Channel 1)


After some time of programming/testing app, bug reappears, however
iwlist scan
still works. I am using
Ubuntu 16.04.1 LTS
with kernel
Linux workstation 4.4.0-38-generic #57-Ubuntu SMP Tue Sep 6 15:42:33 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
.

Is it maybe possible the problem has to something to do with
WiFi
card
Power Management
?

Answer

Look at cfg80211_wext_giwfreq. That is why you get EINVAL of current channel if your Wi-Fi card is not used any connection mode.
The command iwlist scan works because Wi-Fi card switches to AP client mode on the scan time.

Comments