Linux Netlink Source Example

 kernel.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
//#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/skbuff.h>
#include <net/sock.h>

#define MAX_PAYLOAD 1024
#define NLP 31

static struct sock *kernel_sock;

static int exit_flag = 0;

static DECLARE_COMPLETION(exit_completion);

static void recv_handler(struct sock *sk, int length)
{
  printk(KERN_ALERT "message arrives from user\n");
        wake_up(sk->sk_sleep);
}

static int process_message_thread(void * data)
{
        struct sk_buff *skb = NULL;
        struct nlmsghdr *nlhdr = NULL;
        //int len;
        DEFINE_WAIT(wait);

  printk(KERN_ALERT "%s be called\n", __FUNCTION__);

        while (exit_flag == 0){
                prepare_to_wait(kernel_sock->sk_sleep, &wait, TASK_INTERRUPTIBLE);
                schedule();
                finish_wait(kernel_sock->sk_sleep, &wait);

                while ((skb = skb_dequeue(&kernel_sock->sk_receive_queue)) != NULL) {
                        nlhdr = (struct nlmsghdr *)skb->data;
      printk("receive[%s]from user\n", (char*)NLMSG_DATA(nlhdr));
                        if (nlhdr->nlmsg_len < sizeof(struct nlmsghdr)){
                                printk("Corrupt netlink message.\n");
                                continue;
                        }

                        NETLINK_CB(skb).dst_groups = 0;  //group or groups differs
                        netlink_unicast(kernel_sock, skb, nlhdr->nlmsg_pid, 0) ;
                }
        }
        complete(&exit_completion);
        return 0;
}


static int __init netlink_kernel_init(void)
{
        kernel_sock = netlink_kernel_create(NLP, recv_handler);
        if (!kernel_sock){
                printk("Fail to create netlink socket. ");
                return 1;
        }else {
   printk(KERN_ALERT "kernel_sock acquired\n");
  }

        kernel_thread(process_message_thread, NULL, CLONE_KERNEL);
  printk(KERN_ALERT "module installed\n");

        return 0;
}

static void __exit netlink_kernel_exit(void)
{
        exit_flag = 1;
        wake_up(kernel_sock->sk_sleep);
        wait_for_completion(&exit_completion);
        sock_release(kernel_sock->sk_socket);
  printk(KERN_ALERT "module uninstalled\n");
}

module_init(netlink_kernel_init);
module_exit(netlink_kernel_exit);
MODULE_LICENSE("GPL");

------------------------------------------------------------------------------------------------

netlink.c

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <linux/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <stdlib.h>
#include <string.h>

#define MAX_PAYLOAD 1024        /* maximum payload size*/
#define NETLINK_GENERIC  31

int main(void)
{
     struct sockaddr_nl src_addr;
     struct sockaddr_nl dest_addr;
     struct nlmsghdr *nlh = NULL;
  struct msghdr  msg;
     struct iovec iov;
     int sock_fd;
  int ret;

     sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
     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;           /* interested in group 1<<0 */
     ret = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
  if (ret != 0)
  {
   printf("bind error\n");
  }

     memset(&dest_addr, 0, sizeof(dest_addr));
  dest_addr.nl_family = AF_NETLINK;
  dest_addr.nl_pid = 0;
  dest_addr.nl_groups = 0;

     nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
     memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));     
  nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
  printf("pid = %d\n", nlh->nlmsg_pid = getpid());
  nlh->nlmsg_flags = 0;
  strcpy(NLMSG_DATA(nlh), "hello world!\n");

     #if 0  
     iov.iov_base = (void *)nlh;
     iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
     msg.msg_name = (void *)(struct sockaddr *)&dest_addr;
     msg.msg_namelen = sizeof(dest_addr);
     msg.msg_iov = &iov;
     msg.msg_iovlen = 1;
  #endif

  sendto(sock_fd, (void*)nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
  //sendmsg(sock_fd, &msg, 0);
     printf("send complete, Waiting for message from kernel\n");
     /* Read message from kernel */
     //recvmsg(sock_fd, &msg, 0);
  socklen_t len = sizeof(struct sockaddr_nl);
  recvfrom(sock_fd, (void *)nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, &len);
  /* is it ok here? yes */
     printf("Received message payload: [%s]\n", (char*)NLMSG_DATA(nlh));

     close(sock_fd);
  free(nlh);

     return 0;
}

 

Makefile
 

CFLAGES += -w -Wimplicit-function-declaration

ifneq ($(KERNELRELEASE),)
 obj-m := kernel.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
 $(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
 rm -rf *.o *.mod.c *.ko
endi

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值