AF_PACKET套接字解密 二
2014-06-25 12:25
288 查看
当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套接字的接收队列,等待我们的读取。。。一切就是这么简单!
转载地址:http://blog.chinaunix.net/uid-22362479-id-3220136.html
当协议栈准备将数据交给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套接字的接收队列,等待我们的读取。。。一切就是这么简单!
转载地址:http://blog.chinaunix.net/uid-22362479-id-3220136.html
相关文章推荐
- AF_PACKET套接字解密 --- 02
- AF_PACKET套接字解密 --- 01
- AF_PACKET套接字解密 http://write.blog.csdn.net/postedit
- AF_PACKET套接字解密
- AF_PACKET套接字解密 一
- AF_PACKET packet path
- AF_PACKET with CONFIG_PACKET_MMAP,对比其他相似机制: netmap, PF_RING
- 【Linux4.1.12源码分析】AF_PACKET raw socket实现原理分析
- Linux Socket学习 -- 无名套接字 AF_UNIX
- PF_PACKET和AF_PACKET的不同
- 链路层套接字PF_PACKET简介
- 链路层套接字PF_PACKET简介(转)
- AF_INET与套接字
- suricata抓包方式之一 AF_PACKET
- 链路层套接字PF_PACKET简介
- 使用AF_PACKET抓无线数据包
- AF_INET和AF_PACKET区别