Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jpereira/4897d0617e33571c2eaf710dc3f45749 to your computer and use it in GitHub Desktop.
Save jpereira/4897d0617e33571c2eaf710dc3f45749 to your computer and use it in GitHub Desktop.
netlink example code in c
1. Execute make first. This will result in a netlinkKernel.ko output among many others.
2. Execute $ gcc netlinkUser.c -o netlinkUser
3. Insert kernel module by :$ sudo insmod netlinkKernel.ko
4. Run ./netlinkUser to see message and run dmesg to see debug messages
5. Remove module by : $ sudo rmmod netlinkKernel
6. Finally make clean to remove output files.
KDIR := /lib/modules/$(shell uname -r)/build
obj-m += netlinkKernel.o
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.* *.cmd .module* modules* Module* .*.cmd .tmp*
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
//Taken from https://stackoverflow.com/questions/15215865/netlink-sockets-in-c-using-the-3-x-linux-kernel?lq=1
#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#define NETLINK_USER 31
struct sock *nl_sk = NULL;
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 received msg payload:%s\n",(char*)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; /*pid of sending process */
skb_out = nlmsg_new(msg_size,0);
if(!skb_out)
{
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
nlh=nlmsg_put(skb_out,0,0,NLMSG_DONE,msg_size,0);
NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */
strncpy(nlmsg_data(nlh),msg,msg_size);
res=nlmsg_unicast(nl_sk,skb_out,pid);
if(res<0)
printk(KERN_INFO "Error while sending bak to user\n");
}
static int __init hello_init(void) {
printk("Entering: %s\n",__FUNCTION__);
//This is for 3.6 kernels and above.
struct netlink_kernel_cfg cfg = {
.input = hello_nl_recv_msg,
};
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
//nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg,NULL,THIS_MODULE);
if(!nl_sk)
{
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
module_init(hello_init); module_exit(hello_exit);
MODULE_LICENSE("GPL");
//Taken from https://stackoverflow.com/questions/15215865/netlink-sockets-in-c-using-the-3-x-linux-kernel?lq=1
#include <sys/socket.h>
#include <linux/netlink.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define NETLINK_USER 31
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
int main()
{
sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if(sock_fd<0)
return -1;
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "Hello");
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Sending message to kernel\n");
sendmsg(sock_fd,&msg,0);
printf("Waiting for message from kernel\n");
/* Read message from kernel */
recvmsg(sock_fd, &msg, 0);
printf("Received message payload: %s\n", (char *)NLMSG_DATA(nlh));
close(sock_fd);
}
@amoldhamale1105
Copy link

amoldhamale1105 commented May 10, 2023

Doesn't work for me on kernel version 5.15.0-71-generic Ubuntu 20.04. First of all, the module loads when I set unit arg to 30 instead of 31. Then I start the user program (PID 33474). The user program waits indefinitely for the message from kernel. Seems like the message from user program is registered but somehow the registered callback is not getting invoked as expected. Here's my dmesg output:

[ 8620.536837] Entering: hello_init
[ 8651.452447] TRAPS: [auth-link] message from unknown process [33474], peer [1428]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment