* Rtnetlink GETADDR request for 1 specific interface only (by ID)
@ 2024-05-16 9:19 Alexander Sergeev
2024-05-16 11:19 ` Greg KH
0 siblings, 1 reply; 3+ messages in thread
From: Alexander Sergeev @ 2024-05-16 9:19 UTC (permalink / raw)
To: stable@vger.kernel.org; +Cc: regressions@lists.linux.dev
[-- Attachment #1.1: Type: text/plain, Size: 1679 bytes --]
Good morning!
Recently, I have found an issue with `rtnetlink` library that seems to be not intended and/or documented. I have asked about it several times, including here and it was also reported here. Neither in related RFC document nor in rtnetlink manuals the issue is described or mentioned.
In a few words, the issue is: for some reason, rtnetlink GETADDR request works only with NLM_F_ROOT or NLM_F_DUMP flags. Consequently, for instance, filtering by ifa_index field, that would *theoretically* according to docs, allow us to receive address info for 1 specific interface only (by ID) , is not possible. For comparison, similar functionality to GETLINK request (getting information about exactly 1 link by index) is indeed very possible. Instead of the expected output (information about 1 interface only), what is returned is an error message with errno -95, which, as I suppose, can be read as "operation not permitted".
To this email, I attach a small C file illustrating my issue. Feel free to change IFACE_ID define for ID of any network interface present in your system. It illustrates the error.
Please, let me know what you think about this issue. Am I missing something or does it really needs fixing or at least documenting?
Best regards,
Aleksandr Sergeev.
P.S. I have been told that this issue probably won't be addressed, because it "can easily be fixed in user space", however I believe in Linux kernel maintainers team dedication for clear, well-documented and bug-free code; so if this issue is not hard to fix, I would suggest addressing it at least in docs. If it can be useful, I would be more than grateful to provide my help with it.
[-- Attachment #1.2: Type: text/html, Size: 2402 bytes --]
[-- Attachment #2: main.c --]
[-- Type: application/octet-stream, Size: 2471 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if_addr.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define IFACE_ID 3
#define DATA_LENGTH 32768
struct packet {
struct nlmsghdr hdr;
struct ifaddrmsg msg;
};
void generate_address_request(struct packet* pack, int interface_id) {
memset(pack, 0, sizeof(struct packet));
pack->hdr.nlmsg_len = sizeof(struct packet);
pack->hdr.nlmsg_type = RTM_GETADDR;
pack->hdr.nlmsg_flags = NLM_F_REQUEST;
pack->msg.ifa_index = interface_id; // This gets ignored, why?
}
void parse_all_packets(char* messages_bytes, int total_length) {
int index = 0, cursor = 0;
while (cursor < total_length) {
struct nlmsghdr* header = (struct nlmsghdr*) (messages_bytes + cursor);
if (header->nlmsg_type == NLMSG_ERROR) {
int* errnumber = (int*) (messages_bytes + cursor + sizeof(struct nlmsghdr));
printf("Couldn't parse message #%d, errno: %d!\n", index, *errnumber);
} else if (header->nlmsg_type == NLMSG_DONE) {
printf("Message #%d, was the last one!\n", index);
continue;
} else {
struct ifaddrmsg* message = (struct ifaddrmsg*) (messages_bytes + cursor + sizeof(struct nlmsghdr));
printf("Message #%d contains interface #%d data, e.g. prefixlen: %d!\n", index, message->ifa_index, message->ifa_prefixlen);
}
cursor += header->nlmsg_len;
index++;
}
}
int main() {
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(struct sockaddr_nl));
addr.nl_family = AF_NETLINK;
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sock == -1) {
printf("Couldn't create netlink socket, errno: %d!\n", errno);
exit(1);
}
int err = bind(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl));
if (err != 0) {
printf("Couldn't bind netlink socket, errno: %d!\n", errno);
exit(1);
}
socklen_t len = sizeof(struct sockaddr_nl);
getsockname(sock, (struct sockaddr *) &addr, &len);
struct packet pack;
generate_address_request(&pack, IFACE_ID);
write(sock, &pack, sizeof(struct packet));
char buf[DATA_LENGTH];
memset(buf, 0, DATA_LENGTH);
int response_len = read(sock, buf, (socklen_t) DATA_LENGTH);
parse_all_packets(buf, response_len);
}
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: Rtnetlink GETADDR request for 1 specific interface only (by ID)
2024-05-16 9:19 Rtnetlink GETADDR request for 1 specific interface only (by ID) Alexander Sergeev
@ 2024-05-16 11:19 ` Greg KH
[not found] ` <2c63357c6f3220819739d293c9a25f1f-1715860234@onmail.com>
0 siblings, 1 reply; 3+ messages in thread
From: Greg KH @ 2024-05-16 11:19 UTC (permalink / raw)
To: Alexander Sergeev; +Cc: stable@vger.kernel.org, regressions@lists.linux.dev
On Thu, May 16, 2024 at 02:19:15AM -0700, Alexander Sergeev wrote:
> Good morning!
>
> Recently, I have found an issue with `rtnetlink` library that seems to
> be not intended and/or documented. I have asked about it several
> times, including here and it was also reported here. Neither in
> related RFC document nor in rtnetlink manuals the issue is described
> or mentioned.
Great, then why not notify the developers involved in netlink? That's
not the stable and regressions list, sorry, as this is not a regression.
best of luck!
greg k-h
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-05-16 12:07 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-16 9:19 Rtnetlink GETADDR request for 1 specific interface only (by ID) Alexander Sergeev
2024-05-16 11:19 ` Greg KH
[not found] ` <2c63357c6f3220819739d293c9a25f1f-1715860234@onmail.com>
2024-05-16 12:07 ` Greg KH
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox