Chinaunix首页 | 论坛 | 博客
  • 博客访问: 53481
  • 博文数量: 2
  • 博客积分: 838
  • 博客等级: 民兵
  • 技术积分: 40
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-11 11:54
文章分类
文章存档

2012年(2)

分类: LINUX

2012-05-23 22:36:57

当AF_PACKET套接字注册了prot_hook后,怎样进行监听呢,先来看发送:

当协议栈准备将数据交给net_device发送时,它将调用dev_queue_xmit():


点击(此处)折叠或打开

  1. int dev_queue_xmit(struct sk_buff *skb)
  2. {
  3.     struct net_device *dev = skb->dev;
  4. ......
  5.                     rc = dev_hard_start_xmit(skb, dev, txq);
  6. ......
  7. }

点击(此处)折叠或打开

  1. int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
  2.             struct netdev_queue *txq)
  3. {
  4. ......
  5.         if (!list_empty(&ptype_all))
  6.             dev_queue_xmit_nit(skb, dev);
  7. ......
  8. }

由于AF_PACKET套接字注册了prot_hook,将导致dev_queue_xmit_nit()被调用:

点击(此处)折叠或打开

  1. static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
  2. {
  3.     struct packet_type *ptype;
  4.     struct sk_buff *skb2 = NULL;
  5.     struct packet_type *pt_prev = NULL;

  6.     rcu_read_lock();
  7.     list_for_each_entry_rcu(ptype, &ptype_all, list) {
  8.         /* Never send packets back to the socket
  9.          * they originated from - MvS (miquels@drinkel.ow.org)
  10.          */
  11.         if ((ptype->dev == dev || !ptype->dev) &&
  12.          (ptype->af_packet_priv == NULL ||
  13.          (struct sock *)ptype->af_packet_priv != skb->sk)) {
  14.             if (pt_prev) {
  15.                 deliver_skb(skb2, pt_prev, skb->dev);
  16.                 pt_prev = ptype;
  17.                 continue;
  18.             }

  19.             skb2 = skb_clone(skb, GFP_ATOMIC);
  20.             if (!skb2)
  21.                 break;
  22. ......
  23.         }
  24.     }
  25.     if (pt_prev)
  26.         pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);
  27.     rcu_read_unlock();
  28. }
在遍历ptype_all链表时,这里有几点需要着重说明:

1:对于发送的包过滤条件有:
    1). net_device是否是prot_hook指定的dev(NULL代表全部匹配)。
    2). ptype->af_packet_priv在packet_creat()中被设定为自己,故自己发送的包不会被监听。

2:遍历ptype_all时,第一次会复制skb;只有ptype_all中不止1个entry时,将调用deliver_skb()。

3:当退出遍历时,将调用prot_hook的func成员,即packet_rcv()。

4: deliver_skb()仅仅是在调用prot_hook的func成员前增加skb的引用计算数。

点击(此处)折叠或打开

  1. static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
  2.          struct packet_type *pt, struct net_device *orig_dev)
  3. {
  4. ......
  5.     __skb_queue_tail(&sk->sk_receive_queue, skb);
  6. ......
  7. }
经过packet_rcv(),发送的数据包被加入到了AF_PACKET套接字的接收队列,等待我们的读取。。。一切就是这么简单!



阅读(5453) | 评论(0) | 转发(0) |
0

上一篇:AF_PACKET套接字解密 --- 01

下一篇:没有了

给主人留下些什么吧!~~