Netlink in Linux kernel

Netlink, AF_NETLINK, is used to communicate between kernel and userspace.

struct sock *my_nl_sock = NULL;
my_nl_sock = netlink_kernel_create(&init_net, MY_NETLINK_TYPE, &cfg);
  • &init_net is a global variable of type net
  • netlink type defined in linux/include/uapi/linux/netlink.h
  • a config struct of type netlink_kernel_cfg where .groups is for multicast and .input is a function pointer to the callback function when a message is received.
netlink_kernel_release(my_nl_sock)

Receive a message

static void hello_nl_recv_msg(struct sk_buff *skb)
{
    struct nlmsghdr *nlh;
    nlh = (struct nlmsghdr *)skb->data;
    printk(KERN_INFO "Netlink receive msg: %s\n", (char *)nlmsg_data(nlh));
    
    ...
}

skb->data is constructed as a nlmsghdr.

Send a message

static void hello_nl_recv_msg(struct sk_buff *skb)
{
    struct nlmsghdr *nlh;
    int pid;
    struct sk_buff *skb_out;
    int msg_size;
    char *msg = "Hello from kernel";
    int res;

    printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
    msg_size = strlen(msg);
    nlh = (struct nlmsghdr *)skb->data;
    printk(KERN_INFO "Netlink receive msg: %s\n", (char *)nlmsg_data(nlh));

    pid = nlh->nlmsg_pid;
    skb_out = nlmsg_new(msg_size, 0);
    if (!skb_out) {
        printk(KERN_INFO "alloc nlmsg failed\n");
        return;
    }
    nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
    NETLINK_CB(skb_out).dst_group = 0;
    strncpy(nlmsg_data(nlh), msg, msg_size);

    res = nlmsg_unicast(my_nl_sock, skb_out, pid);
    if (res < 0)
        printk(KERN_INFO "nlmsg unicast failed\n");
    return;
}
  • nlh->nlmsg_pid is the pid of the other process(user space process)
  • nlmsg_new is used to create a new netlink message
  • nlmsg_put is used to a wrapper of skb_put
  • We then use strncpy or memcpy to copy data into sk_buff
  • nlmsg_unicast is used to send skb to the specified process
Publish At: Author:Aiden Leong

Read more posts by this author

comments powered by Disqus
皖ICP备16015842号-1