您的位置:首页 > 其它

AF_PACKET套接字解密 --- 02

2013-03-13 18:23 253 查看
AF_PACKET套接字解密 --- 02 2012-05-23
22:36:57

分类: LINUX

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

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

点击(此处)折叠或打开

int dev_queue_xmit(struct sk_buff *skb)

{

struct net_device *dev = skb->dev;

......

rc = dev_hard_start_xmit(skb, dev, txq);

......

}

点击(此处)折叠或打开

int dev_hard_start_xmit(struct
sk_buff *skb, struct net_device *dev,

struct netdev_queue *txq)

{

......

if (!list_empty(&ptype_all))

dev_queue_xmit_nit(skb, dev);

......

}

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

点击(此处)折叠或打开

static void dev_queue_xmit_nit(struct sk_buff *skb, struct
net_device *dev)

{

struct packet_type *ptype;

struct sk_buff *skb2 = NULL;

struct packet_type *pt_prev = NULL;

rcu_read_lock();

list_for_each_entry_rcu(ptype, &ptype_all, list) {

/* Never send packets back to the socket

* they originated from - MvS (miquels@drinkel.ow.org)

*/

if ((ptype->dev == dev || !ptype->dev) &&

(ptype->af_packet_priv == NULL ||

(struct sock *)ptype->af_packet_priv != skb->sk)) {

if (pt_prev) {

deliver_skb(skb2, pt_prev, skb->dev);

pt_prev = ptype;

continue;

}

skb2 = skb_clone(skb, GFP_ATOMIC);

if (!skb2)

break;

......

}

}

if (pt_prev)

pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);

rcu_read_unlock();

}

在遍历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的引用计算数。

点击(此处)折叠或打开

static int packet_rcv(struct sk_buff *skb, struct
net_device *dev,

struct packet_type *pt, struct net_device *orig_dev)

{

......

__skb_queue_tail(&sk->sk_receive_queue, skb);

......

}

经过packet_rcv(),发送的数据包被加入到了AF_PACKET套接字的接收队列,等待我们的读取。。。一切就是这么简单!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: