Установите беспроводной канал, используя Netlink API

Я разрабатываю инструмент WiFi в среде Ubuntu Linux 12.04, и мне нужно переключить интерфейс WiFi между разными каналами.

В настоящее время я нашел решение в исходном коде Wireshark ws80211_utils.c в функции ws80211_set_freq, но я не знаю, как внедрить его в мой исходный код и какие библиотеки включить и как его скомпилировать, чтобы я мог его протестировать.

Проблема в том, что вам нужно использовать слишком много аргументов и флагов. Кроме того, это первый раз, когда я разрабатываю инструмент Wi-Fi Netlink.

Если есть хорошие руководства, с которых можно начать и как использовать вызовы netlink для WiFi, предоставьте мне ссылку.

Большое спасибо, я заранее!

1 ответ

Решение

В текущих версиях Linux nl80211 является правильным способом "общаться" с беспроводной подсистемой. Имейте в виду, что вы не можете произвольно установить канал для каждого драйвера и для каждого режима работы (мастер, клиент, монитор и т. Д.). Некоторые драйверы позволяют изменять канал только в том случае, если соответствующий интерфейс не работает. В таких режимах, как клиент ("управляемый"), канал вообще не может быть установлен, поскольку он определяется точкой доступа.

Также обратите внимание, что не все драйверы беспроводных устройств используют mac80211/cfg80211. Для тех драйверов, которые его не используют, вы должны либо использовать старый API-интерфейс беспроводных расширений, либо (что еще хуже) собственный API-интерфейс конкретного драйвера.

К сожалению, кажется, что нет современной и полной документации интерфейса nl80211. Пожалуйста, поправьте меня, если я ошибаюсь!

Ваш подход к изучению исходного кода других программ кажется разумным. Вы также можете использовать исходный код iw утилита командной строки. iw имеет возможность установить канал:

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

В iw phy.c, строка 91ff. Вы можете найти код, который называется, когда iw wlan0 set channel выполнен. Тем не менее, этот код определенно не легко читать. Похоже, NL80211_CMD_SET_WIPHY Команда в сочетании с NL80211_ATTR_WIPHY_FREQ Атрибут это путь.

В этом SO ответе вы можете найти скелетную программу для использования nl80211. Также код Aircrack-ng (src/osdep/linux.c функция linux_set_channel_nl80211) может выступать в качестве плана.

Принятый ответ в настоящее время правильный, но пока еще не опубликован пример кода, который решает вопрос ОП (даже если он опоздал почти на 4 года), поэтому я подумал, что добавлю это сюда для любых будущих пользователей поисковой системы. Он адаптирован из этого вопроса SO и конкретного файла 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 info или же iwconfig, Здесь нет серьезной проверки ошибок, поэтому все, что вы заметите, это сообщение отправлено или нет. Надеюсь, это поможет любому, как я, перейти с Wireless Extensions на cfg80211 и nl80211.

Другие вопросы по тегам