Skip to content
Advertisement

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?

Advertisement

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.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement