这几天抓着个机会和时间, 了解了下 netlink 这个东东.今天晚上也刚把打印出来.准备没事的时候看看.进一步加深对netlink的了解.
多谢 chinaunix 这个平台, 提供了如此多的资料, 让我知道自己有哪些不知道, 然后拼了老命的学习.这里附上几个链接,因为我的学习,很多都是基于这几个链接.
duanjigang的精华帖.
独孤九贱的帖子.
我花了大概半天的时间, 把 《Linux 系统内核空间与用户空间通信的实现与分析》陈鑫 中间提到的代码, 移植到了 Linux 2.6.32 上.<发现, Linux内核变化确实挺快的.>
这次先贴上我修改过后的代码, 有空再来补补注释.^_^.
1. 将 imp2_k_my.c 编译成 ko, 然后 insmod 到系统.
2. 将 imp2_u.c 编译成应用程序.(我这里编译为 imp2_u. gcc imp2_u.c -o imp2_u.)
3. 将 imp2_u 程序后台运行. (./imp2_u &)
4. 执行一条ping命令. 可以看到 imp2_u 的打印. 和驱动的打印(dmesg | tail -10).
imp2.h
- /*imp1.h*/
- #ifndef __IMP1_H__
- #define __IMP1_H__
- #define IMP1_OPS_BASIC 128
- #define IMP1_SET IMP1_OPS_BASIC
- #define IMP1_GET IMP1_OPS_BASIC
- #define IMP1_MAX IMP1_OPS_BASIC + 1
- #endif
imp2_k_my.c
- #ifndef __KERNEL__
- #define __KERNEL__
- #endif
- #ifndef MODULE
- #define MODULE
- #endif
- #include <linux/netfilter.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/types.h>
- #include <linux/netdevice.h>
- #include <linux/skbuff.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/inet.h>
- #include <linux/in.h>
- #include <linux/ip.h>
- #include <linux/netlink.h>
- #include <linux/spinlock.h>
- #include <net/sock.h>
- #include "imp2.h"
- MODULE_LICENSE("Dual BSD/GPL");
- #define IMP2_K_MY "imp2_k_my:"
- //#define printk(arg) //printkk(KERN_ALERT IMP2_K_MY arg)
- DECLARE_MUTEX(receive_sem);
- static struct sock *mysock;
- struct
- {
- __u32 pid;
- rwlock_t lock;
- } user_proc;
- static int send_to_user(struct packet_info *info)
- {
- int ret = 0;
- int size;
- unsigned char *old_tail;
- struct sk_buff *skb;
- struct nlmsghdr *nlh;
- struct packet_info *packet;
- printk("%s, begin !!! \n", __func__);
- size = NLMSG_SPACE(sizeof(*info));
-
- skb = alloc_skb(size, GFP_ATOMIC);
- old_tail = skb->tail;
- nlh = NLMSG_PUT(skb, 0, 0, IMP2_K_MSG, size - sizeof(*nlh));
- packet = NLMSG_DATA(nlh);
- memset(packet, 0, sizeof(struct packet_info));
- packet->src = info->src;
- packet->dest = info->dest;
- nlh->nlmsg_len = skb->tail - old_tail;
- NETLINK_CB(skb).dst_group = 0;
- read_lock_bh(&user_proc.lock);
- ret = netlink_unicast(mysock, skb, user_proc.pid, MSG_DONTWAIT);
- read_unlock_bh(&user_proc.lock);
-
- printk("%s, end !!! \n", __func__);
- return ret;
-
- nlmsg_failure:
- if(skb)
- kfree_skb(skb);
- return -1;
- }
- static unsigned int icmp_hook_func(unsigned int hooknum,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
- {
- struct iphdr *iph = ip_hdr(skb);
- struct packet_info info;
- //printk("%s, begin !!! \n", __func__);
- if (iph->protocol == IPPROTO_ICMP) {
- read_lock_bh(&user_proc.lock);
-
- if (user_proc.pid != 0) {
- info.src = iph->saddr;
- info.dest = iph->daddr;
- printk("%s, src=%u.%u.%u.%u, dst=%u.%u.%u.%u\n", __func__,
- NIPQUAD(info.src), NIPQUAD(info.dest));
- send_to_user(&info);
- } else {
- printk("%s, no user process running..!\n", __func__);
- }
-
- read_unlock_bh(&user_proc.lock);
- }
- //printk("%s, end !!! \n", __func__);
-
- return NF_ACCEPT;
- }
- #define NF_IP_PRE_ROUTING 0
- static struct nf_hook_ops my_icmp_hook = {
- .hook = icmp_hook_func,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .owner = THIS_MODULE,
- .priority = NF_IP_PRI_FILTER - 1,
- };
- static void my_receive(struct sk_buff *skb)
- {
- struct nlmsghdr *nlh;
- int len;
-
- printk("%s, begin !!!!!\n", __func__);
- nlh = nlmsg_hdr(skb);
- len = skb->len;
- while (NLMSG_OK(nlh, len)) {
- printk("%s, skb_len = %d!!!!!\n", __func__, len);
- write_lock_bh(&user_proc.pid);
- if (nlh->nlmsg_type == IMP2_U_PID) {
- user_proc.pid = nlh->nlmsg_pid;
- } else if (nlh->nlmsg_type == IMP2_CLOSE &&
- nlh->nlmsg_pid == user_proc.pid) {
- user_proc.pid = 0;
- }
- write_unlock_bh(&user_proc.pid);
-
- netlink_ack(skb, nlh, 0);
- nlh = NLMSG_NEXT(nlh, len);
- }
-
- printk("%s, end !!!!!\n", __func__);
- }
- static int __init imp2_k_my_init(void)
- {
- printk("%s, begin !!!!!\n", __func__);
-
- rwlock_init(&user_proc.lock);
-
- mysock = netlink_kernel_create(&init_net, NL_IMP2, 0, my_receive,
- NULL, THIS_MODULE);
- if (!mysock) {
- printk("%s, netlink_kernel_create fail.. !!!!!\n", __func__);
- return -1;
- }
-
- printk("%s, end !!!!!\n", __func__);
- return nf_register_hook(&my_icmp_hook);
- }
- static void __exit imp2_k_my_exit(void)
- {
- printk("%s, begin !!!!!\n", __func__);
- netlink_kernel_release(mysock);
- nf_unregister_hook(&my_icmp_hook);
- printk("%s, end !!!!!\n", __func__);
- }
- module_init(imp2_k_my_init);
- module_exit(imp2_k_my_exit);
用户态程序:
- #include <unistd.h>
- #include <stdio.h>
- #include <linux/types.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <asm/types.h>
- #include <linux/netlink.h>
- #include <signal.h>
- #include "imp2.h"
- struct msg_to_kernel
- {
- struct nlmsghdr hdr;
- };
- struct u_packet_info
- {
- struct nlmsghdr hdr;
- struct packet_info icmp_info;
- };
- static int skfd;
- static void sig_int(int signo)
- {
- struct sockaddr_nl kpeer;
- struct msg_to_kernel message;
- memset(&kpeer, 0, sizeof(kpeer));
- kpeer.nl_family = AF_NETLINK;
- kpeer.nl_pid = 0;
- kpeer.nl_groups = 0;
- memset(&message, 0, sizeof(message));
- message.hdr.nlmsg_len = NLMSG_LENGTH(0);
- message.hdr.nlmsg_flags = 0;
- message.hdr.nlmsg_type = IMP2_CLOSE;
- message.hdr.nlmsg_pid = getpid();
- sendto(skfd, &message, message.hdr.nlmsg_len, 0, (struct sockaddr *)(&kpeer),
- sizeof(kpeer));
- close(skfd);
- exit(0);
- }
- int main(void)
- {
- struct sockaddr_nl local;
- struct sockaddr_nl kpeer;
- int kpeerlen;
- struct msg_to_kernel message;
- struct u_packet_info info;
- int sendlen = 0;
- int rcvlen = 0;
- struct in_addr addr;
- skfd = socket(PF_NETLINK, SOCK_RAW, NL_IMP2);
- if(skfd < 0) {
- printf("can not create a netlink socket\n");
- exit(0);
- }
- memset(&local, 0, sizeof(local));
- local.nl_family = AF_NETLINK;
- local.nl_pid = getpid();
- local.nl_groups = 0;
- if(bind(skfd, (struct sockaddr*)&local, sizeof(local)) != 0) {
- printf("bind() error\n");
- return -1;
- }
- signal(SIGINT, sig_int);
- memset(&kpeer, 0, sizeof(kpeer));
- kpeer.nl_family = AF_NETLINK;
- kpeer.nl_pid = 0;
- kpeer.nl_groups = 0;
- memset(&message, 0, sizeof(message));
- message.hdr.nlmsg_len = NLMSG_LENGTH(0);
- message.hdr.nlmsg_flags = 0;
- message.hdr.nlmsg_type = IMP2_U_PID;
- message.hdr.nlmsg_pid = local.nl_pid;
- sendto(skfd, &message, message.hdr.nlmsg_len, 0,
- (struct sockaddr*)&kpeer, sizeof(kpeer));
- while(1) {
- kpeerlen = sizeof(struct sockaddr_nl);
- rcvlen = recvfrom(skfd, &info, sizeof(struct u_packet_info),
- 0, (struct sockaddr*)&kpeer, &kpeerlen);
- addr.s_addr = info.icmp_info.src;
- printf("src: %s, ", inet_ntoa(addr));
- addr.s_addr = info.icmp_info.dest;
- printf("dest: %s\n", inet_ntoa(addr));
- }
- return 0;
- }
阅读(860) | 评论(0) | 转发(0) |