문제

I am developing a WiFi tool in Ubuntu Linux 12.04 environment and I need to switch the WiFi interface between different channels.

Currently I found the solution in Wireshark source code ws80211_utils.c in function called ws80211_set_freq but I do not know how to implement it into my source code and which libs to include and how to compile so I could test it.

The problem is that there are too many arguments and flags you have to use. Also, this is the first time I develop a netlink wifi tool.

If there are any good manuals available where to start and how to use netlink calls for WiFi please provide me with the link.

Thanks a lot i advance!

도움이 되었습니까?

해결책

In current Linux versions, nl80211 is the right way to "talk" to the wireless subsystem. Be aware that you cannot arbitrarily set a channel with every driver and every operating mode (master, client, monitor etc.) Some drivers allow a channel change only when the corresponding interface is "down". In modes such as client ("managed"), the channel cannot be set at all because it is defined by the access point.

Also note that not all wireless device drivers use mac80211/cfg80211. For those drivers not using it, you either have to use the old wireless extensions API or (even worse) a driver-specific proprietary API.

Sadly, there seems to be no up-to-date and complete documentation of the nl80211 interface. Please correct me if I am wrong!

Your approach of looking into the source code of other programs seems to be a reasonable way. You could also use the source code of the iw command line utility. iw has an option to set the channel:

$ 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-]
…

In iw's phy.c, line 91ff. you can find the code called when iw wlan0 set channel is executed. However, this code is definitely not easy to read. It looks like the NL80211_CMD_SET_WIPHYcommand in conjunction with the NL80211_ATTR_WIPHY_FREQ attribute is the way to go.

In this SO answer you can find a skeleton program for using nl80211. Also, the code of Aircrack-ng (src/osdep/linux.c, function linux_set_channel_nl80211) could act as a blueprint.

다른 팁

The accepted answer is currently correct, but there's no example code posted yet which solves the OP's question (even if nearly 4 years late), so I thought I would add this here for any future search engine users. It's adapted from this SO question and the specific Aircrack-ng file (/src/aircrack-osdep/linux.c, line 1050) that were both previously mentioned.

#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;
}

Compile this with gcc main.c $(pkg-config --cflags --libs libnl-3.0 libnl-genl-3.0). Once executed, check the frequency/channel of your device with e.g. iw wlan1 info or iwconfig. There's no serious error checking here, so all you will notice is if the message was sent or not. Hopefully this helps anyone like me making the transition from Wireless Extensions to cfg80211 and nl80211.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top