how to use the libnl library to trigger nl80211 commands?
Asked Answered
A

1

6

Please can someone give an simple example on how to use libnl to use nl80211. I tried to go through iw source code but it is very confusing. Can any one give a simple program on how to trigger nl80211 commands such as NL80211_CMD_GET_WIPHY using the libnl.

Almire answered 6/2, 2014 at 11:22 Comment(1)
I agree, iw is very hard to get into. Lots of macros and not many comments!Imparadise
I
12

Here is a very basic program sending a NL80211_CMD_GET_INTERFACE, and parsing out the interface type returned in the NL80211_CMD_GET_INTERFACE attribute.

Beware, there is very little error checking here, you should not use any of this program as is! Almost all these functions can fail.

#include "netlink/netlink.h"
#include "netlink/genl/genl.h"
#include "netlink/genl/ctrl.h"
#include <net/if.h>

//copy this from iw
#include "nl80211.h"

static int expectedId;

static int nlCallback(struct nl_msg* msg, void* arg)
{
    struct nlmsghdr* ret_hdr = nlmsg_hdr(msg);
    struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];

    if (ret_hdr->nlmsg_type != expectedId)
    {
        // what is this??
        return NL_STOP;
    }

    struct genlmsghdr *gnlh = (struct genlmsghdr*) nlmsg_data(ret_hdr);

    nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
              genlmsg_attrlen(gnlh, 0), NULL);

    if (tb_msg[NL80211_ATTR_IFTYPE]) {
        int type = nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]);

        printf("Type: %d", type);
    }
}

int main(int argc, char** argv)
{
    int ret;
    //allocate socket
    nl_sock* sk = nl_socket_alloc();

    //connect to generic netlink
    genl_connect(sk);

    //find the nl80211 driver ID
    expectedId = genl_ctrl_resolve(sk, "nl80211");

    //attach a callback
    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM,
            nlCallback, NULL);

    //allocate a message
    nl_msg* msg = nlmsg_alloc();

    nl80211_commands cmd = NL80211_CMD_GET_INTERFACE;
    int ifIndex = if_nametoindex("wlan0");
    int flags = 0;

    // setup the message
    genlmsg_put(msg, 0, 0, expectedId, 0, flags, cmd, 0);

    //add message attributes
    NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifIndex);

    //send the messge (this frees it)
    ret = nl_send_auto_complete(sk, msg);

    //block for message to return
    nl_recvmsgs_default(sk);

    return 0;

nla_put_failure:
    nlmsg_free(msg);
    return 1;
}
Imparadise answered 6/2, 2014 at 13:57 Comment(6)
Thanx a lot the program gave me an overview on how to use the netlink sockets for nl80211 commands. But how to get the scan results using netlinks and how we will come to know when scanning is over.Almire
Well thats a different question, but basically, you send a NL80211_CMD_TRIGGER_SCAN to start a scan off. If you try to start another one when one is running, this would fail. After sending this, you then listen out for the scan to complete when you get a NL80211_CMD_NEW_SCAN_RESULTS. You can then send a NL80211_CMD_GET_SCAN command to ask for the results. You will get one message back for every station found, so be ready to handle multiple messages.Imparadise
Thanks for the help. I got it atlast and found how to scan. My code is now working fine and scanning all surrounding APs.Almire
how to compile it with g++? what needs to be linked on linux?Danidania
gcc -Wall -I/usr/include/libnl3/ main.c -o main -lnl-3 -lnl-genl-3Hydrostat
Please note that nl_send_auto_complete is deprecated. Use nl_send_auto(sk, msg); nlmsg_free(msg); instead.Selfsacrifice

© 2022 - 2024 — McMap. All rights reserved.