在分析AF_PACKET raw socket实现时,我们从创建socket入手来分析, 本篇我们从收包流程入手来分析。在分析协议栈报文接收IP层分析时,我们知道IP层把报文交给raw sock的入口函数是raw_local_deliver。我们从这个函数来看看是如何把一个报文提交给raw socket的。
1、raw_local_deliver函数
int raw_local_deliver(struct sk_buff *skb, int protocol) //该protocol为ip头中的协议
{
int hash;
struct sock *raw_sk;
hash = protocol & (RAW_HTABLE_SIZE - 1); //根据协议类型计算出hash值,hash值共256个,所以不同的ip协议不会重叠
raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); //得到sock,这个sock一定是在创建的时候放到raw_v4_hashinfo中的
/* If there maybe a raw socket we must check - if not we
* don't care less
*/
if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash)) //sock不为空,则把报文提交给sock
raw_sk = NULL;
return raw_sk != NULL;
}
2、raw_v4_input函数
static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
{
struct sock *sk;
struct hlist_head *head;
int delivered = 0;
struct net *net;
read_lock(&raw_v4_hashinfo.lock);
head = &raw_v4_hashinfo.ht[hash]; //得到相同hash的sock链表
if (hlist_empty(head))
goto out;
net = dev_net(skb->dev);
sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol, //sock是否能够接收报文,匹配ip源地址、ip目的地址等
iph->saddr, iph->daddr,
skb->dev->ifindex);
while (sk) { //第一个如果不匹配,后续则不再处理,所以次序很重要,对raw socket肯定是能够匹配的报文的
delivered = 1;
if ((iph->pr