Как отправить команду на сетевой интерфейс с библиотекой netlink
Я начинаю проект, связанный с Wi-Fi, и я завершил один с помощью вызовов Linux ioctl. Теперь я должен сделать то же самое с помощью libnl, поскольку ioctl устарел, я уже прочитал всю основную документацию, но все еще не понимаю, как отправить команду на конкретный интерфейс. Как я могу отправить команду на сетевой интерфейс? скажу, я хочу отправить NL80211_CMD_TRIGGER_SCAN, как я могу это сделать? Любой пример кода очень ценится, так как это будет началом моего путешествия. Как я понимаю, сейчас я должен создать libnl сокет, что-то вроде:
struct nl_sock *socket;
sock = nl_socket_alloc();
а затем составить сообщение nl_msg с моей командой и отправить его, но как?
PS предположим, с помощью nl_send(), но я надеюсь, вы понимаете, что я застрял в точке непонимания идеи о том, как работает эта библиотека
1 ответ
Я также работаю над тем, что связано с Netlink. Я собрал воедино программу, которая работает в моей системе (Debian 3.2.0.4). Это простая программа, которая сначала отправляет сообщение и начинает прослушивать обновления, поступающие от ядра. Я полагаю, что вам придется изменить часть отправки и установить необходимые флаги и т.д.
Одно довольно важное отличие: я не вызываю 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;
}