【问题标题】:Set wireless channel using netlink API使用 netlink API 设置无线信道
【发布时间】:2014-02-18 07:31:57
【问题描述】:

我在Ubuntu Linux 12.04环境下开发WiFi工具,需要在不同通道之间切换WiFi接口。

目前我在名为 ws80211_set_freq 的函数中的 Wireshark 源代码 ws80211_utils.c 中找到了解决方案,但我不知道如何将它实现到我的源代码中,以及要包含哪些库以及如何编译以便我可以测试它。

问题是您必须使用的参数和标志太多。还有,这是我第一次开发netlink wifi工具。

如果有任何好的手册可以从哪里开始以及如何使用 netlink 呼叫 WiFi,请提供链接。

非常感谢我提前!

【问题讨论】:

    标签: c linux wifi netlink


    【解决方案1】:

    在当前的 Linux 版本中,nl80211 是与无线子系统“对话”的正确方式。请注意,您不能为每个驱动程序和每个操作模式(主、客户端、监视器等)任意设置通道。某些驱动程序仅在相应接口“关闭”时才允许更改通道。在客户端(“托管”)等模式下,根本无法设置通道,因为它是由接入点定义的。

    另请注意,并非所有无线设备驱动程序都使用 mac80211/cfg80211。对于那些不使用它的驱动程序,您要么必须使用旧的无线扩展 API,要么(甚至更糟)特定于驱动程序的专有 API。

    遗憾的是,似乎没有关于 nl80211 接口的最新且完整的文档。如果我错了,请纠正我!

    您查看其他程序源代码的方法似乎是一种合理的方法。您也可以使用iw command line utilitysource codeiw 有设置频道的选项:

    $ iw --help
    Usage:  iw [options] command
    Options:
        --debug     enable netlink debugging
        --version   show version (3.2)
    Commands:
    …
    dev <devname> set channel <channel> [HT20|HT40+|HT40-]
    …
    

    iwphy.c,第 91 行。您可以找到执行iw wlan0 set channel 时调用的代码。但是,这段代码绝对不容易阅读。它看起来像 NL80211_CMD_SET_WIPHYcommand 与 NL80211_ATTR_WIPHY_FREQ 属性结合使用是可行的方法。

    this SO answer你可以找到一个使用nl80211的骨架程序。此外,Aircrack-ng 的代码(src/osdep/linux.c,函数linux_set_channel_nl80211)可以作为蓝图。

    【讨论】:

    • 谢谢!没错,我应该将操作模式设置为监控模式,以便能够更改频道,并且我使用了来自 wireshark API 的示例代码。安装 libnl-dev 并使用 -lnl netlink 库标志编译。但是我有时会发生此错误“设备或资源繁忙(-16)”,我不知道是什么原因造成的。
    • 您使用哪个无线驱动程序?您可以查看 cfg80211 的源代码和/或您正在使用的驱动程序,以了解哪些情况会导致 -EBUSY 条件。如果我的回答解决了您的问题,请点赞和/或将其选为已接受的答案。
    • 看来我的驱动没问题。解决方案是:sudo iwconfig wlan0 mode monitor && ifconfig wlan0 down.
    • 你可以在projects website找到一个好的documentation
    • @Phidelux 这是 libnl 和 netlink 套接字的一般文档。 nl80211 没有在那里描述。这就像对 UDP 的描述没有解释 DNS ;-) 我不知道 nl80211 文档,但我真的希望有一个。
    【解决方案2】:

    目前接受的答案是正确的,但还没有发布示例代码来解决 OP 的问题(即使晚了将近 4 年),所以我想我会在此处为任何未来的搜索引擎用户添加此代码。它改编自 SO question 和之前提到的特定 Aircrack-ng 文件(/src/aircrack-osdep/linux.c,第 1050 行)。

    #include <net/if.h>
    #include <netlink/netlink.h>
    #include <netlink/genl/genl.h>
    #include <netlink/genl/ctrl.h>
    #include <linux/nl80211.h>
    
    int main(int argc, char *argv[])
    {
        /* The device's name and the frequency we wish to set it to. */
        char *device = "wlan1";
        int frequencyMhz = 2442;
    
        /* Create the socket and connect to it. */
        struct nl_sock *sckt = nl_socket_alloc();
        genl_connect(sckt);
    
        /* Allocate a new message. */
        struct nl_msg *mesg = nlmsg_alloc();
    
        /* Check /usr/include/linux/nl80211.h for a list of commands and attributes. */
        enum nl80211_commands command = NL80211_CMD_SET_WIPHY;
    
        /* Create the message so it will send a command to the nl80211 interface. */
        genlmsg_put(mesg, 0, 0, genl_ctrl_resolve(sckt, "nl80211"), 0, 0, command, 0);
    
        /* Add specific attributes to change the frequency of the device. */
        NLA_PUT_U32(mesg, NL80211_ATTR_IFINDEX, if_nametoindex(device));
        NLA_PUT_U32(mesg, NL80211_ATTR_WIPHY_FREQ, frequencyMhz);
    
        /* Finally send it and receive the amount of bytes sent. */
        int ret = nl_send_auto_complete(sckt, mesg);
        printf("%d Bytes Sent\n", ret);
    
        nlmsg_free(mesg);
        return EXIT_SUCCESS;
    
        nla_put_failure:
            nlmsg_free(mesg);
            printf("PUT Failure\n");
            return EXIT_FAILURE;
    }
    

    gcc main.c $(pkg-config --cflags --libs libnl-3.0 libnl-genl-3.0) 编译它。 执行后,检查设备的频率/频道,例如iw wlan1 infoiwconfig。这里没有严重的错误检查,所以您只会注意到消息是否已发送。希望这可以帮助像我这样的人从无线扩展过渡到 cfg80211 和 nl80211。

    【讨论】:

    • nl_send_auto_complete 已弃用。使用nl_send_auto
    • NL80211_CMD_SET_WIPHY 也可以使用NL80211_CMD_SET_CHANNEL
    猜你喜欢
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多