The task I am trying to achieve is actually quite simple (multicast the string "TEST" to a userland daemon), but the kernel module doesn't compile. It stops with the error:
passing argument 4 of ‘genlmsg_multicast_allns’ makes integer from pointer without a cast [enabled by default]
But shouldn't it just be the multicast group I defined?
Here is the code for "clarification":
#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <net/netlink.h>
#include <net/genetlink.h>
struct sock *nl_sk = NULL;
static void daemon(void){
struct sk_buff *skb;
void* msg_head;
unsigned char *msg;
struct genl_family my_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = 0,
.name = "family_name",
.version = 1,
.maxattr = 5
};
struct genl_multicast_group my_mc_group = {
.name = "mc_group",
};
msg = "TEST";
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
msg_head = genlmsg_put(skb, 0, 0, &my_genl_family, 0, 21);
nla_put(skb, 0, sizeof(msg), msg);
genlmsg_end(skb, msg_head);
genlmsg_multicast_allns( &my_genl_family, skb, 0, my_mc_group, GFP_KERNEL);
}
static int __init hello_init(void)
{
printk("Entering: %s\n", __FUNCTION__);
printk(KERN_INFO "Calling main function with sockets\n");
struct netlink_kernel_cfg cfg = {
.groups = 1,
.flags = NL_CFG_F_NONROOT_RECV,
};
nl_sk = netlink_kernel_create(&init_net, NETLINK_GENERIC, &cfg);
daemon();
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");
Thanks for your help.
EDIT
This is the client side code:
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/msg.h>
#include <netlink/genl/genl.h>
#include <linux/genetlink.h>
/*
* This function will be called for each valid netlink message received
* in nl_recvmsgs_default()
*/
static int my_func(struct nl_msg *msg, void *arg)
{
//struct nl_msg *nlmsg = nlmsg_alloc_size(GENL_HDRLEN+nla_total_size(sizeof(msg))+36);
printf("Test\n");
return 0;
}
int main(){
struct nl_sock *sk;
int gr_id;
/* Allocate a new socket */
sk = nl_socket_alloc();
/*
* Notifications do not use sequence numbers, disable sequence number
* checking.
*/
nl_socket_disable_seq_check(sk);
/*
* Define a callback function, which will be called for each notification
* received
*/
nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
/* Connect to netlink generic protocol */
nl_connect(sk, NETLINK_GENERIC);
gr_id = genl_family_get_id("family_name");
/* Subscribe to link notifications group */
nl_socket_add_memberships(sk, gr_id, 0);
/*
* Start receiving messages. The function nl_recvmsgs_default() will block
* until one or more netlink messages (notification) are received which
* will be passed on to my_func().
*/
while (1){
nl_recvmsgs_default(sk);
}
return 0;
}
I'd like to start off by saying I'm not a huge fan of Netlink; I think it's rather poorly designed. That said, I think I have the exact answer to the question, so here it goes.
Your core problem is that before using a Generic Netlink family, you first have to register it (this also applies to normal Netlink families). The kernel cannot handle families it doesn't know. Unless you're using an already existing family, this shapes the way you have to approach Netlink.
A Generic Netlink Family belongs to a kernel module. This means a userspace client cannot create a family. In turn, this means you can't just start the client, then have the module send the message right after it creates the family. This is because the family doesn't exist at the moment the client wanted to bind itself to it.
What you need to do is this:
My version of your code follows. This is the kernel module. As you can see, I decided to send the message repeatedly on a timer that runs every two seconds. This gives you time to start the client:
And this is the userspace client:
This is not a direct answer to the netlink question, but an alternative solution. See comments above about netlink limitations.
UDP sockets can be used on Linux to communicate between a user mode process, such as a daemon, and a kernel mode component such as a loadable module.
Daemon code my_udp.c:
Kernel module code k_udp.c:
Note: I've renamed some of the variables and function names from the code I'm using, so you may need to make changes to compile (if I missed something). Be sure to make the ports match between user/kernel components.
The above code was derived from multiple samples on the net and within the Linux kernel.