Charlie Epps
Charlie Epps

Reputation: 119

Who can give me the latest netlink programming samples?

I'm writing a Linux driver using netlink to communicate between user space and kernel space. But I can't find some useful materials, because the netlink has changed from Linux kernel >=2.6.24. Who can give me some suggestions about how to create a netlink socket. Thanks in advance!

Upvotes: 2

Views: 13791

Answers (2)

ctuffli
ctuffli

Reputation: 3580

The code below demonstrates the basics of sending data from a user space application to a kernel module using netlink. This code works on Linux 2.6.28.9 with the git version (ef8ba32) of libnl. For more details, check out the libnl documentation and the code for iw which extensively uses netlink.

Kernel

#include <linux/kernel.h>
#include <linux/module.h>

#include <net/sock.h>
#include <net/netlink.h>

#define MY_MSG_TYPE (0x10 + 2)  // + 2 is arbitrary. same value for kern/usr

static struct sock *my_nl_sock;

DEFINE_MUTEX(my_mutex);

static int
my_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
    int type;
    char *data;

    type = nlh->nlmsg_type;
    if (type != MY_MSG_TYPE) {
        printk("%s: expect %#x got %#x\n", __func__, MY_MSG_TYPE, type);
        return -EINVAL;
    }

    data = NLMSG_DATA(nlh);
    printk("%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", __func__,
            data[0], data[1], data[2], data[3],
            data[4], data[5], data[6], data[7]);
    return 0;
}

static void
my_nl_rcv_msg(struct sk_buff *skb)
{
    mutex_lock(&my_mutex);
    netlink_rcv_skb(skb, &my_rcv_msg);
    mutex_unlock(&my_mutex);
}

static int
my_init(void)
{
    my_nl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0,
            my_nl_rcv_msg, NULL, THIS_MODULE);
    if (!my_nl_sock) {
        printk(KERN_ERR "%s: receive handler registration failed\n", __func__);
        return -ENOMEM;
    }

    return 0;
}

static void
my_exit(void)
{
    if (my_nl_sock) {
        netlink_kernel_release(my_nl_sock);
    }
}

module_init(my_init);
module_exit(my_exit);

User Space

#include <stdio.h>
#include <stdlib.h>

#include <netlink/netlink.h>

#define MY_MSG_TYPE (0x10 + 2)  // + 2 is arbitrary but is the same for kern/usr
int
main(int argc, char *argv[])
{
    struct nl_sock *nls;
    char msg[] = { 0xde, 0xad, 0xbe, 0xef, 0x90, 0x0d, 0xbe, 0xef };
    int ret;

    nls = nl_socket_alloc();
    if (!nls) {
        printf("bad nl_socket_alloc\n");
        return EXIT_FAILURE;
    }

    ret = nl_connect(nls, NETLINK_USERSOCK);
    if (ret < 0) {
        nl_perror(ret, "nl_connect");
        nl_socket_free(nls);
        return EXIT_FAILURE;
    }

    ret = nl_send_simple(nls, MY_MSG_TYPE, 0, msg, sizeof(msg));
    if (ret < 0) {
        nl_perror(ret, "nl_send_simple");
        nl_close(nls);
        nl_socket_free(nls);
        return EXIT_FAILURE;
    } else {
        printf("sent %d bytes\n", ret);
    }

    nl_close(nls);
    nl_socket_free(nls);

    return EXIT_SUCCESS;
}

Upvotes: 7

rsarro
rsarro

Reputation: 566

I have been away of kernel programming from some time now. So I can't give you a direct example on what changes have been introduced. I can tell you how I got to understand the netlink functions and how to use them, reading code. Especially code from NetworkManager or the wireless extensions (iwlib), since that was my area of focus 2 years ago. Those OSS projects always are on top on changes on the kernel and their code is not difficult to understand.

Upvotes: 0

Related Questions