Use netlink to achieve user mode and kernel interaction

于运超 wuyaalan at gmail.com
Wed Jul 10 09:23:34 EDT 2013


Hi,
    nowadays i am learning how to use netlink achieve user mode and kernel
interaction. and when i finsh it ,i found kernel can not get the data from
user mode.
next is my code. can you tell me why?   thank u

user mode code:
   #include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>

void myerr(const char * err_string,int line)
{
    fprintf(stderr,"line:%d ",line);
    perror(err_string);
    exit(1);
}

#define MAX_PAYLOAD  2046
#define NETLINK_TEST 26

/*struct req {
    struct nlmsghdr nlh;
    char buf[MAX_PAYLOAD];
}*/

int main (int argc,char * argv[])
{
    int fd;
    struct sockaddr_nl saddr,daddr;
    int sock_fd;
    struct nlmsghdr *nlhdr = NULL;
    struct iovec iov;
    struct msghdr msg;
    char text[MAX_PAYLOAD];
    int ret;

    if(argc < 2){
        printf("Usage:%s textfile\n",argv[0]);
        exit(1);
    }


    if(fd = (open(argv[1],O_RDWR|O_CREAT,S_IRWXU)) == -1){
        myerr("open",__LINE__);
    }else{
        printf("file open success!\n");
    }


    sock_fd = socket( AF_NETLINK,SOCK_RAW,NETLINK_TEST);
    if( sock_fd < 0 ){
    myerr("sock_fd",__LINE__);
    }

    memset(&saddr,0,sizeof(saddr));
    memset(&daddr,0,sizeof(daddr));

    saddr.nl_family = AF_NETLINK;
    saddr.nl_pid = getpid();
    saddr.nl_groups = 0;

    if(bind(sock_fd,(struct sockaddr * )&saddr,sizeof( saddr)))
    {
        myerr("bind",__LINE__);
    }

    daddr.nl_family = AF_NETLINK;
    daddr.nl_pid = 0;
    daddr.nl_groups = 0;
    nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));

    while(1){
        if(read(fd,text,MAX_PAYLOAD) == -1){
            myerr("read",__LINE__);
        }
//    while(read(fd,text,MAX_PAYLOAD)){
        memcpy(NLMSG_DATA(nlhdr),text,strlen(text));
        memset(&msg,0,sizeof(struct msghdr));

        nlhdr->nlmsg_len = NLMSG_LENGTH(strlen(text));
        nlhdr->nlmsg_pid = getpid();
        nlhdr->nlmsg_flags = 0;

        iov.iov_base = (void *)nlhdr;
        iov.iov_len = nlhdr->nlmsg_len;
        msg.msg_name = (void * )&daddr;
        msg.msg_namelen = sizeof(daddr);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;

        ret = sendmsg(sock_fd,&msg,0);
        if(ret == -1){
            myerr("sendmsg",__LINE__);
        }else{
            printf("usr send message to kernel\n");
            }

    }
    close(sock_fd);
}




kernel module:
#include <linux/module.h>
//#include <linux/kernel.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <net/sock.h>

struct sock *nl_sk = NULL;
#define MAX_PAYLOAD 2046
#define NETLINK_TEST 26

void nl_data_handler(struct sk_buff *__skb)
 {
         struct sk_buff *skb;
         struct nlmsghdr *nlh;
         pid_t pid;
         char str[2046];
       //  int len = NLMSG_SPACE(MAX_PAYLOAD);
            int rc;

     printk("start reading...\n");
         skb = skb_get(__skb);

         if(skb->len >= NLMSG_SPACE(0)) {
                  nlh = nlmsg_hdr(skb);
                  printk("recv:%s\n",(char *)NLMSG_DATA(nlh));
                  memcpy(str,NLMSG_DATA(nlh),sizeof(str));
          pid = nlh->nlmsg_pid;
          printk("pid is %d\n",pid);
                  kfree_skb(skb);

       skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD),GFP_ATOMIC);
      if(!skb){
          printk(KERN_ERR "allocate failed!\n");
        return ;
          }
        nlh = nlmsg_put(skb,0,0,0,MAX_PAYLOAD,0);
        NETLINK_CB(skb).pid = 0;

        memcpy(NLMSG_DATA(nlh),str,sizeof(str));
        printk("net_link: ready send message\n");

        rc = netlink_unicast(nl_sk,skb,pid,MSG_DONTWAIT);
        if(rc < 0){
            printk("can`t unicast skb\n");
        }
        printk("send ok!\n");
    }

  }

  static int __init net_init(void)
  {
          struct net init_net;
//      struct sock *nl_sk = NULL;
          printk("net creat start.....\n");
          nl_sk =
netlink_kernel_create(&init_net,NETLINK_TEST,0,nl_data_handler,NULL,THIS_MODULE);
          if(nl_sk == 0)
          {
                  printk("create netlink faile!\n");
                  return -1;
          }else{
        printk("netlink create success!\n");
        }
          return 0;
  }

  static void __exit net_exit(void)
  {
         printk("lal\n");
      sock_release(nl_sk->sk_socket);
          printk("netlink over!\n");
  }

  module_init(net_init);
  module_exit(net_exit);
  MODULE_LICENSE("GPL");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20130710/491c303f/attachment.html 


More information about the Kernelnewbies mailing list