Mateusz
Mateusz

Reputation: 624

libnl/nl80211 equivalent of iw_set_ext

I started writing a code to handle wifi card using iwconfig/ioctl when I realised that it is depricated and most of applications uses nl80211. I started reading its source code but there is no docs and code is a bit complicated. How can I do simple things like scanning, turning off/on, setting card mode using nl80211 or libnl? This is what I started with iw:

void set_card_mode(MODE mode, std::string ifname)
{
    int skfd = iw_sockets_open();
    struct iwreq wrq;
    wrq.u.mode = static_cast<unsigned int>(mode);
    power_interface(ifname, false);
    if(iw_set_ext(skfd, ifname.c_str(), SIOCSIWMODE, &wrq) < 0)
        throw std::runtime_error("Can set card mode");
}


MODE get_card_mode(std::string ifname)
{
    int skfd = iw_sockets_open();
    struct iwreq wrq;
    if (iw_get_ext (skfd, ifname.c_str(), SIOCGIWMODE, &wrq) >= 0)
    {
        return static_cast<MODE>(wrq.u.mode);
    }
}

Is there any equivalent of iw_get_ext to set/get wifi interface or any api with simple functions like "set_mode" or "power_off"?

Upvotes: 3

Views: 983

Answers (1)

Th. Thielemann
Th. Thielemann

Reputation: 2825

I scan with netlink using the following steps

  1. Prepare and execute NL80211_CMD_TRIGGER_SCAN
  2. Prepare and execute NL80211_CMD_GET_SCAN

    Together with NL80211_CMD_GET_SCAN a callback is registered. In the callback the raw data are parsed as BSS. The IE's are parsed to. See enums with NL80211_BSS_MAX, NL80211_ATTR_MAX from nl80211.h.

Check the return values of every netlink call before process the next step.

Code snippets:

nl_sock* socket = nl_socket_alloc();
genl_connect(socket);
struct nl_msg* msg = nlmsg_alloc();
int driverId = genl_ctrl_resolve(socket, "nl80211"); 
genlmsg_put(msg, 0, 0, driverId, 0, 0, NL80211_CMD_TRIGGER_SCAN, 0);

and fetch with:

genlmsg_put(msg, 0, 0, driverId, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, onScanResult, null);

My callback starts with:

struct genlmsghdr* msgHeader = (genlmsghdr*)nlmsg_data(nlmsg_hdr(msg));
struct nlattr* attributes[NL80211_ATTR_MAX + 1];
struct nlattr* bss[NL80211_BSS_MAX + 1];
if(nla_parse(attributes, NL80211_ATTR_MAX, genlmsg_attrdata(msgHeader, 0), genlmsg_attrlen(msgHeader, 0), NULL) == 0)
{
    // Read the attributes
    // and check for NL80211_ATTR_BSS != 0
}

Most of the scanning results did I found in NL80211_BSS_INFORMATION_ELEMENTS.

if (nla_parse_nested(bss, NL80211_BSS_MAX, attributes[NL80211_ATTR_BSS], bss_policy) == 0)
{ /* read the bss attributes */ }

See NL80211_BSS_INFORMATION_ELEMENTS from nl80211.h and

But I failed to check for WEP privacy. To check for WPA or WPA2 is easy, because there is an extra IE element with ID 48 (Śee IEEE Std 802.11 2012, chapter 8.4.2, free download form ieee side)

Upvotes: 2

Related Questions