netlink multicast from kernel to user space error in linux kernel 3.10 in c -


i have refered following source yd ahhrk

multicast kernel user space via netlink in c

the module insmod correctly , lsmod|less can see there , while try run user space application , have error:

seotsockopt < 0

in user space application , doing group error :

if (setsockopt(sock, 270, netlink_add_membership, &group, sizeof(group)) < 0) {     printf("seotsockopt < 0\n");     return -1; } 

while google other sources , setsockopt , netlink_add_membership doing exact right thing , except yd ahhrk tested in 3.13 , test in 3.10 , have no idea how avoid error , make work .

edit :

the following in code : xyzkernel.c

#include <linux/module.h> #include <linux/kernel.h> #include <linux/netlink.h> #include <net/netlink.h> #include <net/net_namespace.h>  /* protocol family, consistent in both kernel prog , user prog. */ #define myproto netlink_usersock /* multicast group, consistent in both kernel prog , user prog. */ #define mygrp 1  static struct sock *nl_sk = null;  static void send_to_user(void) {     struct sk_buff *skb;     struct nlmsghdr *nlh;     char *msg = "hello kernel";     int msg_size = strlen(msg) + 1;     int res;      pr_info("creating skb.\n");     skb = nlmsg_new(nlmsg_align(msg_size + 1), gfp_kernel);     if (!skb) {         pr_err("allocation failure.\n");         return;     }      nlh = nlmsg_put(skb, 0, 1, nlmsg_done, msg_size + 1, 0);     strcpy(nlmsg_data(nlh), msg);      pr_info("sending skb.\n");     res = nlmsg_multicast(nl_sk, skb, 0, mygrp, gfp_kernel);     if (res < 0)         pr_info("nlmsg_multicast() error: %d\n", res);     else         pr_info("success.\n"); }  static int __init marskernel_init(void) {     pr_info("inserting marskernel module.\n");      nl_sk = netlink_kernel_create(&init_net, myproto, null);     if (!nl_sk) {         pr_err("error creating socket.\n");         return -10;     }      send_to_user();      netlink_kernel_release(nl_sk);     return 0; }  static void __exit marskernel_exit(void) {     pr_info("exiting marskernel module.\n"); }  module_init(marskernel_init); module_exit(marskernel_exit);  module_license("gpl"); 

and client.cpp

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/socket.h> #include <linux/netlink.h> #include <unistd.h>  /* protocol family, consistent in both kernel prog , user prog. */ #define myproto netlink_usersock /* multicast group, consistent in both kernel prog , user prog. */ #define mymgrp 1  int open_netlink(void) {     int sock;     struct sockaddr_nl addr;     int group = mymgrp;      sock = socket(af_netlink, sock_raw, myproto);     if (sock < 0) {         printf("sock < 0.\n");         return sock;     }      memset((void *) &addr, 0, sizeof(addr));     addr.nl_family = af_netlink;     addr.nl_pid = getpid();     /* doesn't work reason. see setsockopt() below. */     /* addr.nl_groups = mymgrp; */      if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {         printf("bind < 0.\n");         return -1;     }      /*      * 270 sol_netlink. see      * http://lxr.free-electrons.com/source/include/linux/socket.h?v=4.1#l314      * ,      * https://stackoverflow.com/questions/17732044/      */     /*     if (setsockopt(sock, 270, netlink_add_membership, &group, sizeof(group)) < 0) {         printf("setsockopt < 0\n");         return -1;     }     */      return sock; } void read_event(int sock) {     struct sockaddr_nl nladdr;     struct msghdr msg;     struct iovec iov;     char buffer[65536];     int ret;      iov.iov_base = (void *) buffer;     iov.iov_len = sizeof(buffer);     msg.msg_name = (void *) &(nladdr);     msg.msg_namelen = sizeof(nladdr);     msg.msg_iov = &iov;     msg.msg_iovlen = 1;      printf("ok, listening.\n");     ret = recvmsg(sock, &msg, 0);     if (ret < 0)         printf("ret < 0.\n");     else         printf("received message payload: %s\n", nlmsg_data((struct nlmsghdr *) &buffer)); }  int main(int argc, char *argv[]) {     int nls;      nls = open_netlink();     if (nls < 0)         return nls;      while (1)         read_event(nls);      return 0; } 

when marked both

/* addr.nl_groups = mymgrp; */ 

and

/*     if (setsockopt(sock, 270, netlink_add_membership, &group, sizeof(group)) < 0) {         printf("setsockopt < 0\n");         return -1;     } */ 

won't encountered run time error , make no sense since mygrp 1 not used anymore , if unmarked addr.nl_groups = mymgrp bind error , unmarked setsockopt setsockopt error ..... have no idea how go on case !!

i had similar problem , think may have been working of same or similar example. there not huge amount can tell without seeing of code. have can pass on couple of things did make multicast work though.

  1. define group 1 in both kernel , userspace code.
  2. remove setsockopt() altogether.

without seeing rest of code, cannot provide more instruction.

good luck

here code used. should along way. however, kernel module not have exit function security reasons.

kernel code

#include <linux/module.h> #include <linux/kernel.h> #include <linux/netlink.h> #include <net/netlink.h> #include <net/sock.h> #include <net/net_namespace.h> #include <linux/skbuff.h>  #define my_group    1  struct sock* socket; struct sk_buff* socket_buff; char *log;  void nl_data_ready(struct sock *sk, int len) {   nlmsg_free(socket_buff); } static void send_to_user(char *message) {     struct nlmsghdr *nlsk_mh;                                                                              char* msg = message;     int res;                                                                                                  socket_buff = nlmsg_new(256, gfp_kernel);                                                                                                                                                                                                                                                      nlsk_mh = nlmsg_put(socket_buff, 0, 0, nlmsg_done, strlen(msg), 0);                            netlink_cb(socket_buff).pid = 0;    // kernel pid                                                        netlink_cb(socket_buff).dst_group = my_group;                                                          strcpy(nlmsg_data(nlsk_mh), msg);                                                                      res = nlmsg_multicast(socket, socket_buff, 0, my_group, gfp_kernel);      if(res < 0)     {         printk("multicast not sent: res < 0\n");         return 0;     }     else     {         printk("multicast sent\n");     }  } void netlink_test(char *buf) {     socket = netlink_kernel_create(&init_net, netlink_usersock, my_group, nl_data_ready, null, this_module);     if (!socket) {         printk("error creating socket.\n");         return -10;     }     else     {         printk("\n\nsocket created successfully\n\n");     }      printk("the message sent user is: %s", buf);     send_to_user(buf);      netlink_kernel_release(socket);      return 0;   } 

userspace code

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/socket.h> #include <linux/netlink.h> #include <unistd.h> #include <errno.h> #include <unistd.h> #define max_payload 1024 /* maximum payload size*/ #define my_group    1  int main(void) {     int sock_fd;     struct sockaddr_nl user_sockaddr;     struct nlmsghdr *nl_msghdr;     struct msghdr msghdr;     struct iovec iov;      char* kernel_msg;      sock_fd = socket(pf_netlink, sock_raw, netlink_usersock);     if(sock_fd<0)     {         printf("error creating socket because: %s\n", strerror(errno));         return -1;     }       memset(&user_sockaddr, 0, sizeof(user_sockaddr));     user_sockaddr.nl_family = af_netlink;     user_sockaddr.nl_pid = getpid();     user_sockaddr.nl_groups = my_group;      bind(sock_fd, (struct sockaddr*)&user_sockaddr, sizeof(user_sockaddr));     while (1) {         nl_msghdr = (struct nlmsghdr*) malloc(nlmsg_space(1024));         memset(nl_msghdr, 0, nlmsg_space(1024));          iov.iov_base = (void*) nl_msghdr;         iov.iov_len = nlmsg_space(1024);          msghdr.msg_name = (void*) &user_sockaddr;         msghdr.msg_namelen = sizeof(user_sockaddr);         msghdr.msg_iov = &iov;         msghdr.msg_iovlen = 1;          printf("waiting receive message\n");         recvmsg(sock_fd, &msghdr, 0);          kernel_msg = (char*)nlmsg_data(nl_msghdr);         printf("kernel message: %s\n", kernel_msg); // print android logs     }      close(sock_fd); } 

also, believe netlink_kernel_create() function has different implementations in different kernel versions. functions have in here might different kernel version (depending on is).

also, think kernel code requires callback function. did not notice in code. code should work article linked more useful figuring out going on.

cheers


Comments

Popular posts from this blog

html - Styling progress bar with inline style -

java - Oracle Sql developer error: could not install some modules -

How to use autoclose brackets in Jupyter notebook? -