title: How to use netlink socket to communicate with a kernel module?
body: <p>I am trying to write a linux kernel module that communicates with user process using netlink. I am using netlink because the user program I want to communicate to communicates only using sockets and I cant change that to add <code>ioctl()</code> or anything.</p>
  
  <p>Problem is that I cant figure out how to do that. I have googled but all examples I found are for old like <a href="http://www.linuxjournal.com/node/7356/print" rel="noreferrer">this one</a> and no longer valid for current kernel versions. I have also looked at <a href="https://stackoverflow.com/questions/862964/who-can-give-me-the-latest-netlink-programming-samples">this SO question</a> but the sample here uses <a href="http://www.infradead.org/~tgr/libnl/" rel="noreferrer">libnl</a> for socket operations but I want to stick to standard socket functions (defined by <code>sys/socket.h</code>). So can some one plz guide me here to some tutorial or guide or some thing that can help me understand the interface and usage of netlink. I would highly appreciate a working example, nothing fancy, just a very basic example of how to establish a connection from a socket in user program to a socket in kernel and then send data from user process to kernel and receive back from kernel.</p>
  
  <p>Also please do not tell me to look at kernel code. I am already doing it but it will take a lot of time and I dont have lot of it left.</p>
  
  <p><strong>Update:</strong>
  After lot of trial and error I have following code which sends message from user program to kernel but the message from kernel to user program i.e using <code>netlink_unicast()</code> is not working. Its not only not working, the call hangs the systems and then I have to restart the machine. Can some one plz take a look and tell me what wrong I am doing. The <code>netlink_unicast()</code> call is commented in the following code. It should be uncommented for kernel to user program message.</p>
  
  <h2>User Program</h2>
  
  <pre><code>#include &lt;sys/socket.h&gt;  
  #include &lt;linux/netlink.h&gt;  
  #define NETLINK_USER 31  
  #define MAX_PAYLOAD 1024  /* maximum payload size*/  
  
  struct sockaddr_nl src_addr, dest_addr;  
  struct nlmsghdr *nlh = NULL;  
  struct iovec iov;  
  int sock_fd;  
  struct msghdr msg;  
  
  void main()  
  {  
      sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);  
      if(sock_fd&lt;0)  
          return -1;  
  
      memset(&amp;src_addr, 0, sizeof(src_addr));  
      src_addr.nl_family = AF_NETLINK;  
      src_addr.nl_pid = getpid();  /* self pid */  
      /* interested in group 1&lt;&lt;0 */  
      bind(sock_fd, (struct sockaddr*)&amp;src_addr,  
        sizeof(src_addr));  
  
      memset(&amp;dest_addr, 0, sizeof(dest_addr));  
      memset(&amp;dest_addr, 0, sizeof(dest_addr));  
      dest_addr.nl_family = AF_NETLINK;  
      dest_addr.nl_pid = 0;   /* For Linux Kernel */  
      dest_addr.nl_groups = 0; /* unicast */  
  
      nlh = (struct nlmsghdr *)malloc(  
                            NLMSG_SPACE(MAX_PAYLOAD));  
      memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));  
      nlh-&gt;nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);  
      nlh-&gt;nlmsg_pid = getpid();  
      nlh-&gt;nlmsg_flags = 0;  
  
      strcpy(NLMSG_DATA(nlh), "Hello");  
  
      iov.iov_base = (void *)nlh;  
      iov.iov_len = nlh-&gt;nlmsg_len;  
      msg.msg_name = (void *)&amp;dest_addr;  
      msg.msg_namelen = sizeof(dest_addr);  
      msg.msg_iov = &amp;iov;  
      msg.msg_iovlen = 1;  
  
      printf("Sending message to kernel\n");  
      sendmsg(sock_fd,&amp;msg,0);  
      printf("Waiting for message from kernel\n");  
  
      /* Read message from kernel */  
      recvmsg(sock_fd, &amp;msg, 0);  
      printf(" Received message payload: %s\n",  
          NLMSG_DATA(nlh));  
      close(sock_fd);  
  }
  </code></pre>
  
  <h2>Kernel Code</h2>
  
  <pre><code>#include &lt;linux/module.h&gt;  
  #include &lt;linux/kernel.h&gt;  
  #include &lt;linux/init.h&gt;  
  #include &lt;net/sock.h&gt;  
  #include &lt;linux/socket.h&gt;  
  #include &lt;linux/net.h&gt;  
  #include &lt;asm/types.h&gt;  
  #include &lt;linux/netlink.h&gt;  
  #include &lt;linux/skbuff.h&gt;  
  
  #define NETLINK_USER 31  
  
  struct sock *nl_sk = NULL;  
  
  static void hello_nl_recv_msg(struct sk_buff *skb)  
  {
          struct nlmsghdr *nlh;  
          int pid;  
  
          printk(KERN_INFO "Entering: %s\n", __FUNCTION__);  
  
          nlh=(struct nlmsghdr*)skb-&gt;data;  
          printk(KERN_INFO "Netlink received msg payload: %s\n",
              (char*)NLMSG_DATA(nlh));  
          pid = nlh-&gt;nlmsg_pid; /*pid of sending process */  
          NETLINK_CB(skb).dst_group = 0; /* not in mcast group */  
          NETLINK_CB(skb).pid = 0;      /* from kernel */  
          //NETLINK_CB(skb).groups = 0; /* not in mcast group */  
          //NETLINK_CB(skb).dst_pid = pid;  
          printk("About to send msg bak:\n");  
          //netlink_unicast(nl_sk,skb,pid,MSG_DONTWAIT);  
  
  }  
  
  static int __init hello_init(void)  
  {  
  
          printk("Entering: %s\n",__FUNCTION__);  
          nl_sk=netlink_kernel_create(&amp;init_net, NETLINK_USER, 0,
                 hello_nl_recv_msg, NULL, THIS_MODULE);  
          if(!nl_sk)  
          {   
                  printk(KERN_ALERT "Error creating socket.\n");  
                  return -10;  
          }  
          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);  
  </code></pre>