linux-kernelnetlink

How to work with NETLINK_KOBJECT_UEVENT protocol in user space?


Let's consider this example code:

#include <linux/netlink.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

#define BUF_SIZE 4096

int main() {
    int fd, res;
    unsigned int i, len;
    char buf[BUF_SIZE];
    struct sockaddr_nl nls;

    fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
    if (fd == -1) {
        return 1;
    }

    memset(&nls, 0, sizeof(nls));
    nls.nl_family = AF_NETLINK;
    nls.nl_pid = getpid();
    nls.nl_groups = 1;

    res = bind(fd, (struct sockaddr *)&nls, sizeof(nls));
    if (res == -1) {
        return 2;
    }

    while (1) {
        len = recv(fd, buf, sizeof(buf), 0);

        printf("============== Received %d bytes\n", len);
        for (i = 0; i < len; ++i) {
            if (buf[i] == 0) {
                printf("[0x00]\n");
            } else if (buf[i] < 33 || buf[i] > 126) {
                printf("[0x%02hhx]", buf[i]);
            } else {
                printf("%c", buf[i]);
            }
        }
        printf("<END>\n");
    }

    close(fd);
    return 0;
}

It listens on netlink socket for events related to hotplug. Basically, it works. However, some parts are unclear for me even after spending whole evening on googling, reading different pieces of documentation and manuals and working through examples.

Basically, I have two questions.

  1. What different values for sockaddr_nl.nl_groups means? At least for NETLINK_KOBJECT_UEVENT protocol.
  2. If buffer allocated for the message is too small, the message will be simply truncated (you can play with the BUF_SIZE size to see that). What this buffer size should be to not lose any data? Is it possible to know in user space length of the incoming message to allocate enough space?

I would appreciate either direct answers as references to kernel code.


Solution

    1. The values represent different multicast groups. A netlink socket can have 31 different multicast groups (0 means unicast) that multicast messages can be sent to. For NETLINK_KOBJECT_UEVENT it looks like it's fixed to 1 see f.ex. here.

    2. You should be able to use getsockopt with level set to SOL_SOCKET and optname set to SO_RCVBUF.