a problem of netlink socket

Hi,

I got a problem about netlink socket.
I want to broadcast a message from kernel to user space.

Here is the kernel code:

struct sock *nl_sk = NULL;
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh;
nl_sk = netlink_kernel_create(NETLINK_UNUSED,
1,
NULL,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
NULL,
#endif
THIS_MODULE);
if(nl_sk != NULL) {
skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD), GFP_ATOMIC);
if(skb != NULL) {
nlh = (struct nlmsghdr *)skb->data;
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = 0;
nlh->nlmsg_flags = 0;
skb_put(skb, NLMSG_SPACE(MAX_PAYLOAD));
strcpy(NLMSG_DATA(nlh), "Greeting from kernel!\n");
NETLINK_CB(skb).pid = 0;
NETLINK_CB(skb).dst_group = 1;
netlink_broadcast(nl_sk, skb, 0, 1, GFP_ATOMIC);
} else if (skb) {
kfree_skb(skb);
}
sock_release(nl_sk->sk_socket);
}

and here is the user space code:

struct sockaddr_nl src_addr;
struct msghdr msg;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sk_nl;
sk_nl = socket(PF_NETLINK, SOCK_RAW, NETLINK_UNUSED);
if (sk_nl < 0)
return -1;
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
src_addr.nl_groups = 1;
bind(sk_nl, (struct sockaddr *)&src_addr, sizeof(src_addr));
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
while (1) {
recvmsg(sk_nl, &msg, 0);
printf("Received from kernel broadcast: %s\n", NLMSG_DATA(nlh));
}
close(sk_nl);

I compiled and run, but no messages were received at the user space.
Can anybody help me?
Thanks!

I have the same question. Im

MariaN73's picture

I have the same question. Im so glad that somebody already submitted the answer. Thank you so much!

_________________
" Nobody's understand you as much as your motor bicycle "

Help regarding Netlink sockets for 2.6 kernels: Kernel module

P's picture

Hi,
I'm a netlink newbie developing a kernel module (as stated above) for 2.6.x kernels.
I'm simply truing to pass a(any) message between the user space and the kernel.

The changes to the netlink APIs from kernel to kernel are confusing.
Below is my kernel code:

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define NETLINK_TEST 17
#define VFW_GROUP 0
#define MSG_SIZE NLMSG_SPACE(1024)

static struct sock *nl_sk = NULL;

static void nltest_rcv(struct sock *sk, int len)
{
struct sk_buff *nl_skb;
struct nlmsghdr *nl_hdr;
int pid;
while ((nl_skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
nl_hdr = (struct nlmsghdr *)nl_skb->data;
pid = nl_hdr->nlmsg_pid;
printk(KERN_ALERT "*** Message from user with PID: (pid = %d) is %s\n", pid, (char*)NLMSG_DATA(nl_hdr));
nl_skb = alloc_skb(MSG_SIZE, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
skb_put(nl_skb, MSG_SIZE);
nl_hdr = (struct nlmsghdr *)nl_skb->data;
nl_hdr->nlmsg_len = MSG_SIZE;
nl_hdr->nlmsg_pid = pid;
nl_hdr->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nl_hdr), "HELLO HELLO HELLO");
NETLINK_CB(nl_skb).pid = 0;
NETLINK_CB(nl_skb).dst_pid = pid;
NETLINK_CB(nl_skb).dst_group = VFW_GROUP;
netlink_unicast(nl_sk, nl_skb, pid, 0);
kfree_skb(nl_skb);
}
}

/* LXR reference:http://lxr.linux.no/#linux+v2.6.26.7/net/netlink/af_netlink.c#L1358
struct sock * netlink_kernel_create
(struct net *net, int unit, unsigned int groups,void (*input)(struct sk_buff *skb),struct mutex *cb_mutex, struct module *module)
*/

static int __init nltest_init(void)
{
struct net *net;
printk(KERN_ALERT "INIT/START: nltest\n");
nl_sk = netlink_kernel_create(net,NETLINK_TEST, VFW_GROUP, nltest_rcv, 0, THIS_MODULE);
if (!nl_sk) {
printk(KERN_ALERT "ERROR: nltest - netlink_kernel_create() failed\n");
return -1;
}
return 0;
}
static void __exit nltest_exit(void)
{
printk(KERN_ALERT "EXIT: nltest\n");
sock_release(nl_sk->sk_socket);

return;
}
module_init(nltest_init);
module_exit(nltest_exit);

MODULE_DESCRIPTION("Module_Test_Netlink");
MODULE_LICENSE("GPL");

when I run a make on this file, it shows the following errors:

root@ubuntu:/home/p# make
make -C /lib/modules/2.6.27-15-generic/build M=/home/p modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.27-15-generic'
CC [M] /home/priyanka/kern.o
/home/p/kern.c: In function ‘nltest_rcv’:
/home/p/kern.c:37: error: ‘struct netlink_skb_parms’ has no member named ‘dst_pid’
/home/p/kern.c: In function ‘nltest_init’:
/home/p/kern.c:54: warning: passing argument 4 of ‘netlink_kernel_create’ from incompatible pointer type
make[2]: *** [/home/p/kern.o] Error 1
make[1]: *** [_module_/home/p] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-2.6.27-15-generic'
make: *** [all] Error 2

The two errors are for
1. netlink_kernel_create function
2. struct netlink_skb_parms

Can anyone help me figure out how to solve these errors?

Thanks!

‘struct netlink_skb_parms’ has no member named ‘dst_pid’

guna's picture

hi,
I'm getting ‘struct netlink_skb_parms’ has no member named ‘dst_pid’ error while compiling my netlink code for linux kernel 2.6.27.
can anyone let me know the alternate way to unicast a message from kernel space to user space without using dst_pid.
I hope dst_pid is not supported in linux kernels above 2.6.23. :(

same problem

thierryD's picture

hi,

I have the same problem and I didn't succed to fix it.
I use separated functions for init and destroy function, and another function for the kernelcode (creating netlink socket and send msgs).
Do you have any ideas ?

Thierry

I encountered similar

Anonymous's picture

I encountered similar situation,

I put the kernel code to a separate function. I called this function from function mymodule_init declared with the use of module_init(mymodule_init),

My client( user space ) program stuck with no response from kernel.

The solution was:
1) call netlink_kernel_create from init function
2) call sock_release from destroy function
3) put the remaining code to another function( lets say test_netlink ), call this function when a particular event occurs( for example when somebody reads /proc entry )

It seems that the bind function have to be called after netlink socket had been crated

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState