I can't seem to get a message from kernel space to user space, or vice-versa. Please advise on where I am going wrong.
Any help much appreciated.
User space code ...
Code:
int main(int argc, char *argv[])
{
init_nl();
while (1) {
recvmsg(nl_sock, &msg, 0);
printf("Received from kernel: %s\n", NLMSG_DATA(nlh));
}
close_nl();
}
int init_nl()
{
nl_sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
if (nl_sock < 0) {
printf("Error: could not create socket\n");
return -1;
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
src_addr.nl_groups = 0; /* not in mcast groups */
bind(nl_sock, (struct sockaddr *) &src_addr, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* kernel pid */
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;
/* fill the netlink msg payload */
strcpy(NLMSG_DATA(nlh), "User Space to Kernel Space Message!");
iov.iov_base = (void *) nlh;
iov.iov_len = nlh->nlmsg_len; //NLMSG_SPACE(MAX_PAYLOAD);
msg.msg_name = (void *) &dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Waiting for msg from kernel\n");
sendmsg(nl_sock, &msg, 0);
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
}
Kernel space code ...
Code:
static int __init my_init(void) {
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh = NULL;
u8 *payload = NULL;
int err = 0;
int seq = 0;
u32 pid = 0;
printk(KERN_INFO "%s() called", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, 0, nl_data_ready,
NULL, THIS_MODULE);
if (nl_sk == NULL) {
printk(KERN_DEBUG "Could not create socket\n");
return -1;
}
size_t len = 0;
skb = alloc_skb(NLMSG_LENGTH(MAX_PAYLOAD), GFP_KERNEL);
if (skb) {
strcpy(skb->data, "MY_INIT");
len = strlen(skb->data);
if (len > 0) {
skb->data[len - 1] = '\0';
}
nlh = (struct nlmsghdr *) skb_put(skb, NLMSG_SPACE(MAX_PAYLOAD));
}
else {
printk("skb doesn't exist!\n");
}
nlh = (struct nlmsghdr *) skb->data;
nlh->nlmsg_len = len;
nlh->nlmsg_pid = 0;
nlh->nlmsg_flags = 0;
nlh->nlmsg_type = 2;
nlh->nlmsg_seq = seq++;
NETLINK_CB(skb).pid = 0;
NETLINK_CB(skb).dst_group = 0;
payload = NLMSG_DATA(nlh);
err = netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
return 0;
}