When sending a "packet" to a rtnetlink socket to get the IP addresses of a specific interface then it answers with what appears to be data for all interfaces.
This is a small example program that illustrates my problem:
#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>
struct packet {
struct nlmsghdr hdr;
struct ifaddrmsg msg;
};
int main() {
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(struct sockaddr_nl));
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
bind(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl));
socklen_t len = sizeof(struct sockaddr_nl);
getsockname(sock, (struct sockaddr *) &addr, &len);
struct packet pack;
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 | NLM_F_DUMP;
pack.hdr.nlmsg_seq = 420; //pick random number here
pack.msg.ifa_index = 2; //This gets ignored, why?
write(sock, &pack, sizeof(struct packet));
char buf[8000];
memset(buf, 0, 8000);
int x = read(sock, buf, (socklen_t) 8000);
for (int i = 0; i < x; i++) {
printf("%i \t: %i\n",i, buf[i]);
}
}
My goal is for RTNETLINK to respond with listing the IP addresses for my network card on index 2. (Loopback is index 1, network card is index 2, confirmed by ip a and if_nametoindex method) I only care about index 2, not any other indices.
Instead I appear to be getting several interfaces and the first interface in the response always has the index 1 (loopback). The first bytes of output on my machine are (with my comments)
0 : 76 <- This packet has 76 bytes length, however read does read way more bytes...
1 : 0
2 : 0
3 : 0
4 : 20 <- RTM_NEWADDR, not really sure why...
5 : 0
6 : 2 <- flags i don't care about
7 : 0
8 : -92 <- sequence number, is equal to input.
9 : 1
10 : 0
11 : 0
12 : -128 <- "Netlink" port number I dont care about
13 : 71
14 : 1
15 : 0
16 : 2 <- struct ifaddrmsg begins here. ifa_family = AF_INET
17 : 8 <- ifa_prefixlen for my network is NOT 8 it should be 24! (8 is for lo iface)
18 : -128 <- flags I dont care about
19 : -2 <- ifa_scope I dont care about
20 : 1 <- Index, why is this 1 for loopback, I told it to output for index 2!
21 : 0
22 : 0
23 : 0
24 : 8 <- First Address Packet
25 : 0
26 : 1
27 : 0
28 : 127 <- loopback iface has 127.0.0.1 not what I wanted to know
29 : 0
30 : 0
31 : 1
32 : 8 <- netmask and other IPs of loopback iface now follow...
33 : 0
I only get the IP addresses for the main network card in the next packet (after byte 78). Afterwards I get the output for all the other network devices. I am using Linux Kernel v. 5.15.31
How can I tell RTNETLINK to only respond with 1 packet for the index 2 network card? Any help with this would be much appreciated.