📄 netlink.c
字号:
#define LINUX#define __KERNEL__#define MODULE#include <linux/kernel.h>#include <linux/module.h>#include <linux/string.h>#include <linux/init.h>#include <linux/types.h>#include <linux/netdevice.h>#include <linux/skbuff.h>#include <linux/inet.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/netlink.h>#include <linux/spinlock.h>#include <asm/semaphore.h>#include <net/sock.h>#include <linux/timer.h>#include <linux/time.h>/* public define */#define IMP_U_PID 0#define IMP_K_MSG 1#define IMP_CLOSE 2#define NL_IMP 31static struct timer_list t_timer;/* Kernel defines */DECLARE_MUTEX(receive_sem); static struct sock *nlfd;struct { __u32 pid; rwlock_t lock;} user_proc;static void kernel_receive(struct sock *sk,int len){ do { struct sk_buff *skb; printk("kernel_receive: somebody call this function. \n"); if(down_trylock(&receive_sem)) return; while((skb = skb_dequeue(&sk->receive_queue)) != NULL) { struct nlmsghdr *nlh = NULL; if(skb->len >= sizeof(struct nlmsghdr)) { nlh = (struct nlmsghdr *)skb->data; printk("kernel_receive: type:0x%x pid:%x.\n", nlh->nlmsg_type, nlh->nlmsg_pid); if((nlh->nlmsg_len >= sizeof(struct nlmsghdr)) && (skb->len >= nlh->nlmsg_len)) { if(nlh->nlmsg_type == IMP_U_PID) { write_lock_bh(&user_proc.pid); user_proc.pid = nlh->nlmsg_pid; write_unlock_bh(&user_proc.pid); } else if(nlh->nlmsg_type == IMP_CLOSE) { write_lock_bh(&user_proc.pid); if(nlh->nlmsg_pid == user_proc.pid) { user_proc.pid = 0; } write_unlock_bh(&user_proc.pid); } } } kfree_skb(skb); } up(&receive_sem); }while(nlfd && nlfd->receive_queue.qlen);}static int send_to_user(unsigned char *message){ int ret; int size; unsigned char *old_tail; struct sk_buff *skb; struct nlmsghdr *nlh; printk("send_to_user: Start to send message to user.msg:%s, user_proc.pid:%d\n", message, user_proc.pid); if(!user_proc.pid) return 0; size = NLMSG_SPACE(strlen(message)); skb = alloc_skb(size,GFP_ATOMIC); old_tail = skb->tail; nlh = NLMSG_PUT(skb,0,0,IMP_K_MSG,size - sizeof(*nlh)); strcpy(NLMSG_DATA(nlh), message); nlh->nlmsg_len = skb->tail - old_tail; NETLINK_CB(skb).dst_groups = 0; read_lock_bh(&user_proc.lock); ret = netlink_unicast(nlfd,skb,user_proc.pid,MSG_DONTWAIT); read_unlock_bh(&user_proc.lock); /* In netlink_unicast, it will release skb buffer. There is no need to free ourself. */ printk("send_to_user: ret value:%d \n", ret); return ret;nlmsg_failure: if(skb) { kfree_skb(skb); } return -1;}void hello(unsigned long data){ char buf[32]; sprintf(buf, "Hello. jiffies:%d\n", jiffies); send_to_user(buf); mod_timer(&t_timer, jiffies+5*HZ);}int init_module(){ printk("Perry :Enter\n"); rwlock_init(&user_proc.lock); nlfd = netlink_kernel_create(NL_IMP, kernel_receive); if(!nlfd) { printk("can't create a netlink socket \n"); return -1; } init_timer(&t_timer); t_timer.expires = jiffies + 100; t_timer.function = hello; add_timer(&t_timer); return 0;}void cleanup_module(void){ del_timer_sync(&t_timer); if(nlfd) { sock_release(nlfd->socket); } printk("Perry:leave\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -