如何使用 netlink 库向网络接口发送命令

Posted

技术标签:

【中文标题】如何使用 netlink 库向网络接口发送命令【英文标题】:How to send command to network interface with netlink library 【发布时间】:2013-08-20 15:14:43 【问题描述】:

我正在启动与 wifi 相关的项目,并且我已经完成了一个使用 linux ioctl 调用的项目。现在我必须在 libnl 的帮助下做同样的事情,因为现在不推荐使用 ioctl,我已经阅读了所有核心文档,但仍然不明白如何在特定接口上发送命令。如何将命令发送到网络接口?说我想发送 NL80211_CMD_TRIGGER_SCAN,我该怎么做?非常感谢任何示例代码,因为它将是我旅程的开始。 据我所知,我现在必须创建 libnl 套接字,例如:

struct nl_sock *socket;
sock = nl_socket_alloc();

然后用我的命令编写 nl_msg 消息并发送它,但是如何?

附:假设使用 nl_send(),但我希望你明白我停留在不理解这个 lib 是如何工作的想法的地方

【问题讨论】:

【参考方案1】:

我也在做一些涉及 netlink 的事情。我拼凑了一个似乎可以在我的系统上运行的程序(debian 3.2.0.4)。这是一个简单的程序,它首先发送一个 msg 并开始监听来自内核的更新。我相信您将不得不更改发送部分并设置必要的标志等。

一个相当重要的区别:我不调用 nl_socket_alloc,而是创建一个常规套接字。我确定我在那里有一些错误,你可以直截了当。希望对您有所帮助:

#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/cache.h>
#include <netlink/route/link.h>
//#include <>

#define NETLINK_USER 31

#define MAX_PAYLOAD 1024

using std::cout;
using std::endl;

int sequence_number = 0;

void sendNetLinkMsg(int fd) 
    struct nlmsghdr *nh = 0;
    struct sockaddr_nl sa;
    struct iovec iov =  nh, nh->nlmsg_len ;
    struct msghdr msg;

    msg = &sa, sizeof(sa), &iov, 1, NULL, 0, 0;
    memset(&sa, 0, sizeof(sa));
    sa.nl_family = AF_NETLINK;
    nh->nlmsg_pid = getpid();
    nh->nlmsg_seq = ++sequence_number;
    nh->nlmsg_flags |= NLM_F_ACK;

    sendmsg(fd, &msg, 0);


void recvNetLinkMsg(int fd, struct msghdr* msg, char* buf) 
    int len;
    struct nlmsghdr *nh;
    len = recvmsg(fd, msg, 0);
    for (nh = (struct nlmsghdr *) buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) 
        if (nh->nlmsg_type == NLMSG_DONE)
            break;

        if (nh->nlmsg_type == NLMSG_ERROR) 
            cout << "Error" << endl;
        
        if (nh->nlmsg_type == RTM_DELROUTE)
            cout << "Delete route" << endl;
        else if (nh->nlmsg_type == RTM_NEWROUTE)
            cout << "New route" << endl;
        else 
            cout << "Unknown msg: " << nh->nlmsg_type << endl;
        
    


int main() 
    struct sockaddr_nl sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));
    sockAddr.nl_family = AF_NETLINK;
    sockAddr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;

    int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    bind(fd, (struct sockaddr *) &sockAddr, sizeof(sockAddr));

    char buf[4096];
    struct iovec iov =  buf, sizeof(buf) ;
    struct msghdr msg;

    msg = &sockAddr, sizeof(sockAddr), &iov, 1, NULL, 0, 0;

    sendNetLinkMsg(fd);

    while (true) 
        recvNetLinkMsg(fd, &msg, buf);
    
    return 0;

【讨论】:

我使用了这个页面并在那里运行了大部分代码,没有任何重大问题。对解析消息有很大帮助:http://maz-programmersdiary.blogspot.com/2011/09/netlink-sockets.html 另外,发现此页面很有帮助:http://softengcrunch.blogspot.com/2011/01/communicating-with-kernel-via-netlink.html

以上是关于如何使用 netlink 库向网络接口发送命令的主要内容,如果未能解决你的问题,请参考以下文章

用户态监控网络接口updown事件

Windows IPC 模拟 Linux Unix 域和 Netlink 套接字

linux下netlink的使用简介

如何使用 Redth PushSharp 库向多个平台发送推送通知?

如何使用netlink进行IPC?

linux 内核中Netlink