【问题标题】:Error in issuing Netlink command get_station发出 Netlink 命令 get_station 时出错
【发布时间】:2018-05-07 22:42:58
【问题描述】:

我想通过libnl获取使用Netlink的电台信息。我发出命令NL80211_CMD_GET_STATION。在发送消息之前,我根据nl80211.h 文件中的指令添加属性NL80211_ATTR_MACNL80211_ATTR_IFINDEX 以及它们各自的值。我写了一个带有错误检查的简单代码:

int main(int argc, char **argv)
{
    struct nl_sock *sk;                 /* Socket */
    struct nl_msg *msg;                 /* Netlink message struct */
    int err;                            /* Message flags */
    unsigned char mac_adr[ETH_ALEN];    /* MAC address */
    char path[50]="", if_name[] = "wlp4s0"; /* Interface name */
    strcat(path, "/sys/class/net/");
    strcat(path, if_name);
    strcat(path, "/address");
    /* allocate socket */
    if (!(sk = nl_socket_alloc()))
    {
        printf("Error in creating socket!\n");
        return -1;
    }
    /* Connect to generic netlink */
    if (genl_connect(sk) < 0)
    {
        printf("Error in connecting socket to Generic Netlink!\n");
        return -1;
    }
    /* Find the nl80211 driver ID */
    NL_family = genl_ctrl_resolve(sk, "nl80211");
    if (NL_family < 0)
    {
        printf("Error in getting nl80211 Netlink message ID!\n");
        return -1;
    }
    /* Attach a callback */
    err = nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM,
                nlCallback, NULL);
    if (err < 0)
    {
        printf("Error in a Callback to Netlink socket!\n");
        return -1;
    }
    /* Create a new message */
    if (!(msg = nlmsg_alloc()))
    {
        printf("Error in allocating Netlink message!\n");
        return -1;
    }
    /* Setup the message */
    if (!genlmsg_put(msg, 0, NL_AUTO_SEQ, NL_family, 0, 0,
            NL80211_CMD_GET_STATION, 0))
    {
        printf("Error in creating Netlink message!\n");
        return -1;
    }
    /* Add message attributes */
    /* Putting MAC address */
    if (get_mac(mac_adr, path) < 0)
    {
        printf ("Error in getting MAC address!\n");
        return -1;
    }
    NLA_PUT(msg, NL80211_ATTR_MAC, sizeof(mac_adr), mac_adr);
    /* Interface attribute */
    NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
    /* Send the messge (this frees it) */
    err = nl_send_auto(sk, msg);
    if (err < 0)
    {
        printf ("Error in sending the messages!\n");
        return -1;
    }
    printf("Sent %d Bytes\n", err);
    /* Block execution to receive the answer from the kernel */
    err = nl_recvmsgs_default(sk);
    if (err < 0)
    {
        printf("Error in receiving Netlink message! Error: %s\n", nl_geterror(err));
        return -1;
    }
    return 0;

nla_put_failure:
    nlmsg_free(msg);
    printf("Error in Attribute Put\n");
    return -1;
}

当我运行程序时,它会在代码末尾使用函数nl_recvmsgs_default(sk) 尝试从内核接收回复时生成错误object not found

我使用相同的代码通过命令NL80211_CMD_GET_INTERFACE 获取相同接口的类型。我使用属性NL80211_ATTR_IFINDEX 发送此命令的消息。该程序适用于NL80211_CMD_GET_INTERFACE,它会打印接口类型!因此,我怀疑我获取 MAC 地址的方式有问题。 这是我为从文件中获取 MAC 地址而编写的函数:

int get_mac(unsigned char *mac_adr, char *path)
{
    int c, i = 0, j = 0, d1, d2;
    char mac_str[20];

    FILE *file;
    file = fopen(path, "r");
    if (file) {
        while ((c = getc(file)) != EOF)
            mac_str[i++] = c;

        mac_str[i] = 0;
        fclose(file);
    }
    else return -1;

    for (i=0; i<=(ETH_ALEN-1)*3; i+=3)
    {
        if (mac_str[i]>='0' && mac_str[i]<='9')
            d1 = mac_str[i] - '0';
        else if (mac_str[i]>='a' && mac_str[i]<='f')
            d1 = mac_str[i] - 'a' + 10;
        if (mac_str[i+1]>='0' && mac_str[i+1]<='9')
            d2 = mac_str[i+1] - '0';
        else if (mac_str[i+1]>='a' && mac_str[i+1]<='f')
            d2 = mac_str[i+1] - 'a' + 10;

        mac_adr[j++] = d1*16+d2;
    }
    return 1;
}

如果接口名称是wlp4s0,则包含MAC 地址的文件将位于路径/sys/class/net/wlp4s0/address。什么会导致执行NL80211_CMD_GET_STATION 时出现问题?

是否有可能因为命令NL80211_CMD_GET_STATION 需要root 用户而NL80211_CMD_GET_INTERFACE 不需要而出现此错误? 但我当然使用NL80211_CMD_GET_STATION 和root 用户。

【问题讨论】:

    标签: linux-kernel linux-device-driver netlink


    【解决方案1】:

    无线客户端应该连接到AP,你需要使用AP的MAC地址而不是客户端的MAC地址。

    您可以查看使用 NL80211_CMD_GET_STATION here (source of iw tool) 的示例

    【讨论】:

    • 设置标志NLM_F_DUMP怎么样?它带来了什么?我想在特定界面上获取链接的RSSI。通过设置该标志,程序可以工作。我认为是因为它不需要 MAC 地址。
    • 顺便说一句,我刚刚用 AP(这是我家的无线路由器)的 MAC 地址进行了测试,它仍然给我这个错误。
    • @Masoud,我的客户端已连接到 AP。我从 iw 工具(print_sta_handle)中获取了您的代码和回调,并且程序无需任何更改即可运行。
    • @Masoud,您是以 root 身份启动程序吗?
    • 是的,我愿意。我在与您提到的print_sta_handle 相同的函数中使用代码。
    猜你喜欢
    • 1970-01-01
    • 2018-06-06
    • 1970-01-01
    • 2020-02-14
    • 2021-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多