免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3900 | 回复: 11
打印 上一主题 下一主题

netlink问题,通讯当机 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-09-19 15:30 |只看该作者 |倒序浏览
同志们,这个是我修改的论坛前辈的代码。操作系统是redhat5.0,内核是2.6.18。

现在的情况是:
代码在没有通讯的时候内核态程序正常,获得的user_proc.pid为0,
运行用户态代码,则死机。

代码如下:

头文件:

  1. #ifndef __IMP2_H__
  2. #define __IMP2_H__

  3. #define IMP2_U_PID   0
  4. #define IMP2_K_MSG   1
  5. #define IMP2_CLOSE   2

  6. #define NL_IMP2      31

  7. struct packet_info
  8. {
  9.   __u32 src;
  10.   __u32 dest;
  11.   unsigned char protocol;
  12.   unsigned short tot_len;
  13. };

  14. #endif
复制代码


内核态代码:
  1. #ifndef _KERNEL_
  2. #define _KERNEL_
  3. #endif

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

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

  22. DECLARE_MUTEX(receive_sem);

  23. static struct sock *nlfd;

  24. struct {
  25.     __u32 pid;
  26.     rwlock_t lock;
  27. }user_proc;
  28. #if 0
  29. static void kernel_receive(struct sock *sk,int len)
  30. {
  31. //        do
  32.         {
  33.                 struct sk_buff *skb;
  34.                 if(down_trylock(&receive_sem))
  35.                         return;
  36. //                while((skb = skb_dequeue(&sk->receive_queue)) != NULL)
  37.                 {
  38.                         {
  39.                                 struct nlmsghdr *nlh = NULL;
  40.                                 if(skb->len >= sizeof(struct nlmsghdr))
  41.                                 {
  42.                                         nlh = (struct nlmsghdr *)skb->data;
  43.                                         if((nlh ->nlmsg_len >= sizeof(struct nlmsghdr)) && (skb->len >= nlh->nlmsg_len))
  44.                                         {
  45.                                                 if(nlh->nlmsg_type == IMP2_U_PID)
  46.                                                 {
  47.                                                         write_lock_bh(&user_proc.pid);
  48.                                                         if(nlh ->nlmsg_pid == user_proc.pid)
  49.                                                         {
  50.                                                                 user_proc.pid = 0;       
  51.                                                         }
  52.                                                         write_unlock_bh(&user_proc.pid);
  53.                                                 }
  54.                                         }
  55.                                 }
  56.                         }       
  57.                         kfree_skb(skb);
  58.                 }
  59.                 up(&receive_sem)
  60. //        }while(nlfd && nlfd->receive_queue.qlen);
  61. }
  62. #endif
  63. #if 1

  64. static void kernel_receive(struct sock *sk,int len)
  65. {

  66.         struct sk_buff *skb = NULL;
  67. #if 1
  68.     struct nlmsghdr *nlh = NULL;
  69.     //printk("%s: skb->user: %d\n", __func__, atomic_read(&skb->users)); return;
  70.     if(down_trylock(&receive_sem))
  71.         return;

  72.     if(skb->len < sizeof(struct nlmsghdr))
  73.     goto out;

  74. //    nlh = nlmsg_hdr(skb);
  75.         nlh =  (struct nlmsghdr *)skb->data;

  76.     if((nlh->nlmsg_len >= sizeof(struct nlmsghdr))
  77.             && (skb->len >= nlh->nlmsg_len))
  78.     {
  79.                 printk("--------::::::::----------------");
  80.         if(nlh->nlmsg_type == IMP2_U_PID)
  81.         {
  82.             write_lock_bh(&user_proc.lock);
  83.             user_proc.pid = nlh->nlmsg_pid;
  84.                         printk("::::::user_proc.pid= %d\n",user_proc.pid);
  85.             write_unlock_bh(&user_proc.lock);
  86.         }
  87.         else if(nlh->nlmsg_type == IMP2_CLOSE)
  88.         {
  89.             write_lock_bh(&user_proc.lock);
  90.             if(nlh->nlmsg_pid == user_proc.pid)
  91.                 user_proc.pid = 0;
  92.             write_unlock_bh(&user_proc.lock);
  93.         }
  94.     }

  95.     //kfree_skb(skb);
  96.     out:
  97.         up(&receive_sem);
  98. #endif
  99. }
  100. #endif
  101. static int send_to_user(struct packet_info *info)
  102. {
  103.     int ret;
  104.     int size;
  105.     unsigned char *old_tail;
  106.     struct sk_buff *skb;
  107.     struct nlmsghdr *nlh;
  108.     struct packet_info *packet;

  109.     size = NLMSG_SPACE(sizeof(*info));

  110.     skb = alloc_skb(size, GFP_ATOMIC);
  111.     old_tail = skb->tail;

  112.     nlh = NLMSG_PUT(skb, 0, 0, IMP2_K_MSG, size-sizeof(*nlh));
  113.     packet = NLMSG_DATA(nlh);
  114.     memset(packet, 0, sizeof(struct packet_info));

  115.     packet->src = info->src;
  116.     packet->dest = info->dest;
  117.     packet->protocol = info->protocol;
  118.     packet->tot_len = info->tot_len;

  119.     nlh->nlmsg_len = skb->tail - old_tail;
  120.    
  121.         NETLINK_CB(skb).pid = 0;
  122.         NETLINK_CB(skb).dst_group = 0;
  123.        
  124.     read_lock_bh(&user_proc.lock);
  125.     ret = netlink_unicast(nlfd, skb, user_proc.pid, MSG_DONTWAIT);
  126.     read_unlock_bh(&user_proc.lock);

  127.     return ret;

  128. nlmsg_failure:
  129.     if(skb)
  130.         kfree_skb(skb);
  131.     return -1;
  132. }

  133. static unsigned int get_icmp(unsigned int hook,
  134.         struct sk_buff **pskb,
  135.         const struct net_device *in,
  136.         const struct net_device *out,
  137.         int (*okfn)(struct sk_buff *))
  138. {
  139.     printk("%s\n", __func__);

  140.         //struct sk_buff *sb = *pskb;
  141.         struct iphdr *ip = (*pskb)->nh.iph;
  142.     struct packet_info info;

  143.         //ip = sb->nh.iph;
  144.         switch(ip->protocol)
  145.                         {
  146.                                 case 89:
  147.                                         printk("::OSPF::\n");
  148.                                         break;
  149.                                 case 1:
  150.                                         printk("::ICMP::\n");
  151.                                         break;
  152.                                 case 2:
  153.                                         printk("::IGMP::\n");
  154.                                         break;
  155.                                 case 6:
  156.                                         printk("::TCP::\n");
  157.                                         break;
  158.                                 case 17:
  159.                                         printk("::UDP::\n");
  160.                                         break;
  161.                         }
  162.                 printk(" [ %d ]\n ",ip->tot_len );
  163.         
  164.                 read_lock_bh(&user_proc.lock);
  165.                 printk("_____:::pid_2::%d\n",user_proc.pid );
  166.         if(user_proc.pid != 0)
  167.                 {
  168.            read_unlock_bh(&user_proc.lock);
  169.             info.src = ip->saddr;
  170.             info.dest = ip->daddr;
  171.                         info.tot_len = ip->tot_len;
  172.             info.protocol = ip->protocol;
  173.             printk("before send\n");
  174.             send_to_user(&info);
  175.             printk("after send\n");
  176.         }
  177.        else
  178.                 {
  179.                         read_unlock_bh(&user_proc.lock);
  180.                 }
  181.        
  182.         printk("-------------------send to user end-----------");
  183.     return NF_ACCEPT;
  184. }

  185. static struct nf_hook_ops imp2_ops =
  186. {
  187.     .hook = get_icmp,
  188.     .pf = PF_INET,
  189.     .hooknum =NF_IP_PRE_ROUTING,
  190.     .priority = NF_IP_PRI_FIRST,
  191. };

  192. static int __init init(void)
  193. {
  194.           rwlock_init(&user_proc.lock);

  195.     //nlfd = netlink_kernel_create(NL_IMP2, kernel_receive);
  196.     //nlfd = netlink_kernel_create(NL_IMP2, 0, 0,THIS_MODULE);
  197.         printk("------------------------------------------------create----------\n");
  198.     nlfd = netlink_kernel_create(NL_IMP2, 0, kernel_receive,THIS_MODULE);
  199.         printk("---create----end------!!!\n");
  200.         //nlfd = netlink_kernel_create(&init_net, NL_IMP2, 0, kernel_receive, NULL, THIS_MODULE);

  201.     if(!nlfd) {
  202.         printk("can not create a netlink socket\n");
  203.         return -1;
  204.     }
  205.     return nf_register_hook(&imp2_ops);
  206. }

  207. static void __exit fini(void)
  208. {
  209.     if(nlfd) {
  210.         sock_release(nlfd->sk_socket);
  211.     }
  212.     nf_unregister_hook(&imp2_ops);
  213. }

  214. module_init(init);
  215. module_exit(fini);
复制代码


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

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

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

  19. static int skfd;

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

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

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

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

  34.   close(skfd);
  35.   exit(0);
  36. }

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

  48.     skfd = socket(PF_NETLINK, SOCK_RAW, NL_IMP2);
  49.     if(skfd < 0)
  50.     {
  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.     {
  60.         printf("bind() error\n");
  61.         return -1;
  62.     }
  63. #if 1
  64.     signal(SIGINT, sig_int);

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

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

  74.     sendto(skfd, &message, message.hdr.nlmsg_len, 0,
  75.          (struct sockaddr*)&kpeer, sizeof(kpeer));
  76. #endif
  77.    printf("RUN");
  78.     while(1)
  79.     {
  80.         kpeerlen = sizeof(struct sockaddr_nl);
  81.         rcvlen = recvfrom(skfd, &info, sizeof(struct u_packet_info),
  82.                         0, (struct sockaddr*)&kpeer, &kpeerlen);
  83.         if(rcvlen > 0)
  84.         {
  85.             ++count;
  86.         }
  87.         printf("------------------------------\n");
  88.         printf("receive packet :: %d ",count);
  89.         addr.s_addr = info.icmp_info.src;
  90.         printf(" src: %s, ", inet_ntoa(addr));
  91.         addr.s_addr = info.icmp_info.protocol;
  92.   //    printf(" Packet:%s",addr.s_addr);
  93.         if(addr.s_addr == 6)
  94.         {
  95.             printf("TCP");
  96.         }
  97.         else if(addr.s_addr == 17)
  98.         {
  99.             printf("UDP");
  100.         }
  101.         else if(addr.s_addr == 1)
  102.         {
  103.             printf("ICMP");
  104.         }
  105.         else if(addr.s_addr == 2)
  106.         {
  107.             printf("IGMP");
  108.         }
  109.         else printf("unkown");
  110.         addr.s_addr = info.icmp_info.dest;
  111.         printf(" dest: %s\n", inet_ntoa(addr));
  112.         addr.s_addr = info.icmp_info.tot_len;
  113.         printf("::%d::",addr.s_addr);
  114.         printf("-----------------------------\n");
  115.         
  116.     }

  117.     return 0;
  118. }
复制代码



另,驱动程序的调试方法大家能给我指导下否?
相关的比较好的书籍或者帖子。

[ 本帖最后由 zengrui0342 于 2008-9-19 15:32 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-09-19 16:36 |只看该作者
write_lock_bh(&user_proc.pid);

http://linux.chinaunix.net/bbs/viewthread.php?tid=1015818
不过改后的版本可能需要更高的版本

论坛徽章:
0
3 [报告]
发表于 2008-09-19 16:51 |只看该作者
对,谢谢关注,

这个就是按照那个帖子里面改的。

原版本在我的ubuntu8.04上完全可以运行。

但我们的服务器(产品环境)是RED HAT 5.0

内核版本为2.6.18。



分析问题得到:

内核程序在用户态程序没运行的时候

user_proc.pid ==0
也就是说没有运行sedtouser函数。

运行用户态代码后。
其会向内核态程序发送数据。

这个时候,直接死机。

内核态的接收处理函数和发送给用户态数据的函数都有问题的嫌疑。

论坛徽章:
0
4 [报告]
发表于 2008-09-19 16:59 |只看该作者
thx

我先改下。

论坛徽章:
0
5 [报告]
发表于 2008-09-19 17:12 |只看该作者
结果还是一样。。。
:em12: :em12: :em12:

论坛徽章:
0
6 [报告]
发表于 2008-09-21 15:54 |只看该作者
。。。。


能给点解决问题的建议么?

论坛徽章:
0
7 [报告]
发表于 2008-09-25 09:48 |只看该作者
BUG报告。。

牛人帮我看看,问题出在哪里?

Screenshot.png (983.26 KB, 下载次数: 26)

Screenshot.png

论坛徽章:
0
8 [报告]
发表于 2008-09-25 11:32 |只看该作者
总算 解决了

用啦最笨的方法。

将关键函数一个一个注释。

最后发现是发送
  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));

    kpeer.nl_pid = 0
应设置成getpid()

罪过罪过。

论坛徽章:
0
9 [报告]
发表于 2008-09-25 15:14 |只看该作者
...

死机问题没啦。
不过好像就通讯一次。。

用户程序打开。显示内核给他发的信息,不过信息本身有问题。

而且没再继续发送。。

论坛徽章:
0
10 [报告]
发表于 2008-09-25 15:58 |只看该作者
很郁闷。

做的徒劳功。

改成pid就将处理进程变成自己了。。

所以还是不对
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP