2

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.

0 Answers0