LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 10-31-2021, 07:21 AM   #1
kernel_learner
LQ Newbie
 
Registered: Oct 2021
Distribution: Ubuntu
Posts: 1

Rep: Reputation: Disabled
Netlink nlmsg_multicast() function returning -ESRCH even though the Netlink userspace application running.


I am writing a Linux kernel module and Linux userspace program and trying to establish a multicast netlink communication between them targeted from Linux kernel module to Linux userspace program.
Aim:
1)Linux userspace program will be added to a custom group and will be listening for incoming messages from Linux kernel module.

2)The Linux kernel module will send a multicast message which the user space program will receive and will just display the received payload.

The code for Netlink kernel module and Netlink userspace program is as follows.
/**********types**************/
typedef unsigned long _uint64_t;
typedef unsigned int _uint32_t;
typedef signed int _int32_t;
typedef short unsigned int _uint16_t;
typedef short signed int _int16_t;
typedef unsigned char _uint8_t;
typedef char _int8_t;

/***********************User space program***********************/
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<linux/netlink.h>
#include"types.h"

#define NETLINK_USER 31 //Custom netlink protocol number.
#define NOTIFICATION_GROUP (((_uint32_t)0x00000001)<<3)
_int32_t main(void)
{
_int32_t sock_fd;
struct msghdr msg;
_int8_t rcv_buffer[500] = {'\0'};
struct iovec iov[2];
struct nlmsghdr nlh;
sock_fd = socket(AF_NETLINK,SOCK_RAW,NETLINK_USER);
if(sock_fd & (0x00000001<<31))
{
perror("Failed to create a socket");
return -1;
}
printf("Successfully created a socket.\n");
struct sockaddr_nl src_addr,dst_addr;
memset(&src_addr,0,sizeof(src_addr));
memset(&dst_addr,0,sizeof(dst_addr));
memset(&nlh,0,sizeof(nlh));
memset(&msg,0,sizeof(msg));
src_addr.nl_family = AF_NETLINK; //socket family
src_addr.nl_groups = NOTIFICATION_GROUP;
src_addr.nl_pid = getpid();
bind(sock_fd,(struct sockaddr *)&src_addr,sizeof(src_addr));
iov[0].iov_base = &nlh;
iov[0].iov_len = sizeof(nlh);
iov[1].iov_base = rcv_buffer;
iov[1].iov_len = sizeof(rcv_buffer);
msg.msg_name = &dst_addr;
msg.msg_namelen = sizeof(dst_addr);
msg.msg_iov = iov;
msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]);
printf("Waiting to receive message from kernel......\n");
recvmsg(sock_fd,&msg,0);
//(nl_msg_hdr+1) will point to start of payload data
printf("Received payload message : 0x%X\n",*(_uint32_t *)NLMSG_DATA(&nlh));
close(sock_fd);
return 0;
}

/***********************Linux kernel module**************************/
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/netlink.h>
#include<net/sock.h>
#include<linux/delay.h>
#include"types.h"

#define DATA_TYPE_u8 0
#define DATA_TYPE_u16 1
#define DATA_TYPE_u32 2
#define DATA_TYPE_u64 3
#define DATA_TYPE_STR 4
#define KERNEL_PID 0

#define NETLINK_CUSTOM_PROTCOL 31
#define NOTIFICATION_GROUP (((_uint32_t)0x00000001)<<3)
static struct sock *nl_sk = NULL;
static void send_notification_to_usp(void *data_ptr,_uint8_t data_type);
static _int32_t __init __nl_init(void)
{
nl_sk = netlink_kernel_create(&init_net,NETLINK_CUSTOM_PROTCOL,NULL);
if(nl_sk)
{
pr_info("Netlink socket creation : success.\n");
mdelay(20000);
_uint32_t __data = 0x11223344;
send_notification_to_usp(&__data,DATA_TYPE_u32);
}
else
{
pr_info("Netlink socket creation : failed.\n");
}
pr_info("%s module inserted in kernel.\n",__FUNCTION__);
return SUCCESS;
}

static void __exit __nl_exit(void)
{
//nlmsg_free(skbuff_out);
netlink_kernel_release(nl_sk);
pr_info("%s module removed from kernel.\n",__FUNCTION__);
}

static void send_notification_to_usp(void *data_ptr,_uint8_t data_type)
{
if(data_ptr)
{
struct sk_buff *skbuff_out = NULL;
_uint8_t u8_data;
_uint16_t u16_data;
_uint32_t u32_data;
_uint64_t u64_data;
_uint8_t *str_data = NULL;
struct nlmsghdr *nlh = NULL;
if(data_type == DATA_TYPE_u8)
{
u8_data = *(_uint8_t *)data_ptr;
skbuff_out = nlmsg_new(NLMSG_ALIGN(sizeof(u8_data)),GFP_KERNEL);
if(skbuff_out)
{
nlh = nlmsg_put(skbuff_out,KERNEL_PID,0,NLMSG_DONE,NLMSG_ALIGN(sizeof(u8_data)),0);
*(_uint8_t *)NLMSG_DATA(nlh) = u8_data;
}
else
{
pr_info("Failed to alocate socket buffer-u8_data.\n");
}
}
else if(data_type == DATA_TYPE_u16)
{
u16_data = *(_uint16_t *)data_ptr;
skbuff_out = nlmsg_new(NLMSG_ALIGN(sizeof(u16_data)),GFP_KERNEL);
if(skbuff_out)
{
nlh = nlmsg_put(skbuff_out,KERNEL_PID,0,NLMSG_DONE,NLMSG_ALIGN(sizeof(u8_data)),0);
*(_uint16_t *)NLMSG_DATA(nlh) = u16_data;
}
else
{
pr_info("Failed to alocate socket buffer-u16_data.\n");
}
}
else if(data_type == DATA_TYPE_u32)
{
u32_data = *(_uint32_t *)data_ptr;
skbuff_out = nlmsg_new(NLMSG_ALIGN(sizeof(u32_data)),GFP_KERNEL);
if(skbuff_out)
{
nlh = nlmsg_put(skbuff_out,KERNEL_PID,0,NLMSG_DONE,NLMSG_ALIGN(sizeof(u32_data)),0);
*(_uint32_t *)NLMSG_DATA(nlh) = u32_data;
}
else
{
pr_info("Failed to alocate socket buffer-u32_data.\n");
}
}
else if(data_type == DATA_TYPE_u64)
{
u64_data = *(_uint64_t *)data_ptr;
skbuff_out = nlmsg_new(NLMSG_ALIGN(sizeof(u64_data)),GFP_KERNEL);
if(skbuff_out)
{
nlh = nlmsg_put(skbuff_out,KERNEL_PID,0,NLMSG_DONE,NLMSG_ALIGN(sizeof(u64_data)),0);
*(_uint64_t *)NLMSG_DATA(nlh) = u64_data;
}
else
{
pr_info("Failed to alocate socket buffer-u64_data.\n");
}
}
else if(data_type == DATA_TYPE_STR)
{
str_data = (_uint8_t *)data_ptr;
skbuff_out = nlmsg_new(NLMSG_ALIGN(strlen(str_data)),GFP_KERNEL);
if(skbuff_out)
{
nlh = nlmsg_put(skbuff_out,KERNEL_PID,0,NLMSG_DONE,NLMSG_ALIGN(strlen(str_data)),0);
strncpy((_int8_t *)NLMSG_DATA(nlh),str_data,strlen(str_data));
}
else
{
pr_info("Failed to alocate socket buffer-str_data.\n");
}
}
//The below function is already in nlmsg_multicast().
_int32_t res;
res = nlmsg_multicast(nl_sk,skbuff_out,KERNEL_PID,NOTIFICATION_GROUP,GFP_KERNEL);
if(res<0)
{
pr_info("Failed to send multicast message to USP.\n");
pr_info("res : %d.\n",res);
//perror("Error message");
}
else
{
pr_info("Success send multicast message to USP.\n");
}
}
}
module_init(__nl_init);
module_exit(__nl_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Author name");
MODULE_VERSION("0.1");
MODULE_DESCRIPTION("Netlink kernel module");

The code compiles fine without any errors. The issues which are coming while running the code are as follows.

1)If the user program is run first without the kernel module being inserted in kernel first. Then the user program fails to create a socket and gives error message "Protocol not supported". So is this normal behavior or the kernel module needs to be inserted first and then the user program needs to be run.

2)If the kernel module is inserted first and then the userspace program is run then the userspace program is able to create socket and proceed forward but no message is received by userspace program and the userspace program keeps waiting.The kernel dmesg logs indicates that the nlmsg_multicast() function returns -ESRCH which indicates "There are no listeners for this group".

Linux Kernel version : 5.11.0

Any inputs on how to solve the above two issues will be helpful.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] PNF: Even Though I Passed true to Function, Always Puts false des_a Programming 15 08-04-2020 02:31 PM
[SOLVED] read function call returning more amount of data than wiritten using write function chakka.lokesh Programming 1 09-11-2014 03:14 AM
[SOLVED] Access Generic Netlink from userspace yaplej Programming 4 11-10-2012 02:16 AM
Running userspace application in realtime john_erlandsson Programming 11 03-27-2012 09:18 AM
[SOLVED] Apache slow at start and not running even though it says it's started!!! YassBoss Linux - Server 6 09-06-2009 11:10 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 04:40 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration