Chinaunix首页 | 论坛 | 博客
  • 博客访问: 237978
  • 博文数量: 51
  • 博客积分: 235
  • 博客等级: 入伍新兵
  • 技术积分: 25
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-16 23:16
文章分类

全部博文(51)

文章存档

2016年(3)

2015年(35)

2014年(12)

2013年(1)

分类: LINUX

2015-07-28 15:54:17

原文地址:Linux之netlink学习 作者:hk2305621

这几天抓着个机会和时间, 了解了下 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

  1. /*imp1.h*/
  2. #ifndef __IMP1_H__
  3. #define __IMP1_H__

  4. #define IMP1_OPS_BASIC 128
  5. #define IMP1_SET IMP1_OPS_BASIC
  6. #define IMP1_GET IMP1_OPS_BASIC
  7. #define IMP1_MAX IMP1_OPS_BASIC + 1

  8. #endif

imp2_k_my.c

  1. #ifndef __KERNEL__
  2. #define __KERNEL__
  3. #endif

  4. #ifndef MODULE
  5. #define MODULE
  6. #endif

  7. #include <linux/netfilter.h>
  8. #include <linux/module.h>
  9. #include <linux/kernel.h>
  10. #include <linux/init.h>
  11. #include <linux/types.h>
  12. #include <linux/netdevice.h>
  13. #include <linux/skbuff.h>
  14. #include <linux/netfilter_ipv4.h>
  15. #include <linux/inet.h>
  16. #include <linux/in.h>
  17. #include <linux/ip.h>
  18. #include <linux/netlink.h>
  19. #include <linux/spinlock.h>
  20. #include <net/sock.h>

  21. #include "imp2.h"

  22. MODULE_LICENSE("Dual BSD/GPL");

  23. #define IMP2_K_MY "imp2_k_my:"
  24. //#define printk(arg) //printkk(KERN_ALERT IMP2_K_MY arg)

  25. DECLARE_MUTEX(receive_sem);
  26. static struct sock *mysock;

  27. struct
  28. {
  29.     __u32 pid;
  30.     rwlock_t lock;
  31. } user_proc;

  32. static int send_to_user(struct packet_info *info)
  33. {
  34.     int ret = 0;
  35.     int size;
  36.     unsigned char *old_tail;

  37.     struct sk_buff *skb;
  38.     struct nlmsghdr *nlh;
  39.     struct packet_info *packet;

  40.     printk("%s, begin !!! \n", __func__);

  41.     size = NLMSG_SPACE(sizeof(*info));
  42.     
  43.     skb = alloc_skb(size, GFP_ATOMIC);
  44.     old_tail = skb->tail;

  45.     nlh = NLMSG_PUT(skb, 0, 0, IMP2_K_MSG, size - sizeof(*nlh));
  46.     packet = NLMSG_DATA(nlh);
  47.     memset(packet, 0, sizeof(struct packet_info));

  48.     packet->src = info->src;
  49.     packet->dest = info->dest;

  50.     nlh->nlmsg_len = skb->tail - old_tail;
  51.     NETLINK_CB(skb).dst_group = 0;

  52.     read_lock_bh(&user_proc.lock);
  53.     ret = netlink_unicast(mysock, skb, user_proc.pid, MSG_DONTWAIT);
  54.     read_unlock_bh(&user_proc.lock);
  55.     
  56.     printk("%s, end !!! \n", __func__);

  57.     return ret;
  58.     
  59. nlmsg_failure:
  60.     if(skb)
  61.         kfree_skb(skb);
  62.     return -1;
  63. }

  64. static unsigned int icmp_hook_func(unsigned int hooknum,
  65.              struct sk_buff *skb,
  66.              const struct net_device *in,
  67.              const struct net_device *out,
  68.              int (*okfn)(struct sk_buff *))
  69. {
  70.     struct iphdr *iph = ip_hdr(skb);
  71.     struct packet_info info;

  72.     //printk("%s, begin !!! \n", __func__);

  73.     if (iph->protocol == IPPROTO_ICMP) {
  74.         read_lock_bh(&user_proc.lock);
  75.         
  76.         if (user_proc.pid != 0) {
  77.             info.src = iph->saddr;
  78.             info.dest = iph->daddr;
  79.             printk("%s, src=%u.%u.%u.%u, dst=%u.%u.%u.%u\n", __func__,
  80.                 NIPQUAD(info.src), NIPQUAD(info.dest));
  81.             send_to_user(&info);
  82.         } else {
  83.             printk("%s, no user process running..!\n", __func__);
  84.         }
  85.         
  86.         read_unlock_bh(&user_proc.lock);
  87.     }
  88.     //printk("%s, end !!! \n", __func__);
  89.     
  90.     return NF_ACCEPT;
  91. }

  92. #define NF_IP_PRE_ROUTING    0

  93. static struct nf_hook_ops my_icmp_hook = {
  94.     .hook = icmp_hook_func,
  95.     .pf = PF_INET,
  96.     .hooknum = NF_IP_PRE_ROUTING,
  97.     .owner = THIS_MODULE,
  98.     .priority = NF_IP_PRI_FILTER - 1,
  99. };

  100. static void my_receive(struct sk_buff *skb)
  101. {
  102.     struct nlmsghdr *nlh;
  103.     int len;
  104.     
  105.     printk("%s, begin !!!!!\n", __func__);

  106.     nlh = nlmsg_hdr(skb);
  107.     len = skb->len;

  108.     while (NLMSG_OK(nlh, len)) {

  109.         printk("%s, skb_len = %d!!!!!\n", __func__, len);

  110.         write_lock_bh(&user_proc.pid);
  111.         if (nlh->nlmsg_type == IMP2_U_PID) {
  112.             user_proc.pid = nlh->nlmsg_pid;
  113.         } else if (nlh->nlmsg_type == IMP2_CLOSE &&
  114.                 nlh->nlmsg_pid == user_proc.pid) {
  115.             user_proc.pid = 0;
  116.         }
  117.         write_unlock_bh(&user_proc.pid);
  118.         
  119.         netlink_ack(skb, nlh, 0);
  120.         nlh = NLMSG_NEXT(nlh, len);
  121.     }
  122.   
  123.     printk("%s, end !!!!!\n", __func__);
  124. }

  125. static int __init imp2_k_my_init(void)
  126. {
  127.     printk("%s, begin !!!!!\n", __func__);
  128.     
  129.     rwlock_init(&user_proc.lock);
  130.     
  131.     mysock = netlink_kernel_create(&init_net, NL_IMP2, 0, my_receive,
  132.         NULL, THIS_MODULE);
  133.     if (!mysock) {
  134.         printk("%s, netlink_kernel_create fail.. !!!!!\n", __func__);
  135.         return -1;
  136.     }
  137.     
  138.     printk("%s, end !!!!!\n", __func__);

  139.     return nf_register_hook(&my_icmp_hook);
  140. }

  141. static void __exit imp2_k_my_exit(void)
  142. {
  143.     printk("%s, begin !!!!!\n", __func__);
  144.     netlink_kernel_release(mysock);
  145.     nf_unregister_hook(&my_icmp_hook);
  146.     printk("%s, end !!!!!\n", __func__);
  147. }

  148. module_init(imp2_k_my_init);
  149. module_exit(imp2_k_my_exit);

 

用户态程序:

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <linux/types.h>
  4. #include <string.h>
  5. #include <sys/socket.h>
  6. #include <arpa/inet.h>
  7. #include <asm/types.h>
  8. #include <linux/netlink.h>
  9. #include <signal.h>
  10. #include "imp2.h"

  11. struct msg_to_kernel
  12. {
  13.     struct nlmsghdr hdr;
  14. };

  15. struct u_packet_info
  16. {
  17.   struct nlmsghdr hdr;
  18.   struct packet_info icmp_info;
  19. };

  20. static int skfd;

  21. static void sig_int(int signo)
  22. {
  23.     struct sockaddr_nl kpeer;
  24.     struct msg_to_kernel message;

  25.     memset(&kpeer, 0, sizeof(kpeer));
  26.     kpeer.nl_family = AF_NETLINK;
  27.     kpeer.nl_pid = 0;
  28.     kpeer.nl_groups = 0;

  29.     memset(&message, 0, sizeof(message));
  30.     message.hdr.nlmsg_len = NLMSG_LENGTH(0);
  31.     message.hdr.nlmsg_flags = 0;
  32.     message.hdr.nlmsg_type = IMP2_CLOSE;
  33.     message.hdr.nlmsg_pid = getpid();

  34.     sendto(skfd, &message, message.hdr.nlmsg_len, 0, (struct sockaddr *)(&kpeer),
  35.          sizeof(kpeer));

  36.     close(skfd);
  37.     exit(0);
  38. }

  39. int main(void)
  40. {
  41.     struct sockaddr_nl local;
  42.     struct sockaddr_nl kpeer;
  43.     int kpeerlen;
  44.     struct msg_to_kernel message;
  45.     struct u_packet_info info;
  46.     int sendlen = 0;
  47.     int rcvlen = 0;
  48.     struct in_addr addr;

  49.     skfd = socket(PF_NETLINK, SOCK_RAW, NL_IMP2);
  50.     if(skfd < 0) {
  51.         printf("can not create a netlink socket\n");
  52.         exit(0);
  53.     }

  54.     memset(&local, 0, sizeof(local));
  55.     local.nl_family = AF_NETLINK;
  56.     local.nl_pid = getpid();
  57.     local.nl_groups = 0;
  58.     if(bind(skfd, (struct sockaddr*)&local, sizeof(local)) != 0) {
  59.         printf("bind() error\n");
  60.         return -1;
  61.     }

  62.     signal(SIGINT, sig_int);

  63.     memset(&kpeer, 0, sizeof(kpeer));
  64.     kpeer.nl_family = AF_NETLINK;
  65.     kpeer.nl_pid = 0;
  66.     kpeer.nl_groups = 0;

  67.     memset(&message, 0, sizeof(message));
  68.     message.hdr.nlmsg_len = NLMSG_LENGTH(0);
  69.     message.hdr.nlmsg_flags = 0;
  70.     message.hdr.nlmsg_type = IMP2_U_PID;
  71.     message.hdr.nlmsg_pid = local.nl_pid;

  72.     sendto(skfd, &message, message.hdr.nlmsg_len, 0,
  73.         (struct sockaddr*)&kpeer, sizeof(kpeer));

  74.     while(1) {
  75.         kpeerlen = sizeof(struct sockaddr_nl);
  76.         rcvlen = recvfrom(skfd, &info, sizeof(struct u_packet_info),
  77.         0, (struct sockaddr*)&kpeer, &kpeerlen);

  78.         addr.s_addr = info.icmp_info.src;
  79.         printf("src: %s, ", inet_ntoa(addr));
  80.         addr.s_addr = info.icmp_info.dest;
  81.         printf("dest: %s\n", inet_ntoa(addr));
  82.     }

  83.     return 0;
  84. }


 

阅读(818) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~