// 向raw sock传递skb
// 步骤:
// 1.根据协议号获取监听指定protocol的sock
// 2.向raw sock传递skb
1.1 int raw_local_deliver(struct sk_buff *skb, int protocol)
{
int hash;
struct sock *raw_sk;
//获取监听指定协议的raw sock
hash = protocol & (RAW_HTABLE_SIZE - 1);
raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
//向raw socket传递
if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash))
raw_sk = NULL;
return raw_sk != NULL;
}
// 向raw sock传递skb
// 步骤:
// 1.获取raw sock链表, 查找可接收此skb的sock
// 1.1 如果raw sock指定了协议号,源地址,目的地址,设备号,则逐项匹配
// 2.向sock传递skb的拷贝
1.2 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];
if (hlist_empty(head))
goto out;
net = dev_net(skb->dev);
sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
iph->saddr, iph->daddr,
skb->dev->ifindex);
while (sk) {
delivered = 1;
//如果有注册的sock raw,传递一份skb拷贝
struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
if (clone)
raw_rcv(sk, clone);
//匹配sock,协议号,源地址,目的地址,设备号
sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
iph->saddr, iph->daddr,
skb->dev->ifindex);
}
out:
read_unlock(&raw_v4_hashinfo.lock);
return delivered;
}
// 添加skb到sock队列
// 步骤:
// 1.调整skb->data指向ip报头
// 2.添加skb到struct sock的接收队列
1.3 int raw_rcv(struct sock *sk, struct sk_buff *skb)
{
//调整skb->data指针指向ip报头
skb_push(skb, skb->data - skb_network_header(skb));
//添加skb到struct sock队列上
raw_rcv_skb(sk, skb);
return 0;
}
// 添加skb到sock队列
// 步骤:
// 1.断开skb与入口设备之间的联系
// 2.将skb添加到sock->sk_receive_queue
// 3.通知sock数据已经准备好
1.4 int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
int err;
int skb_len;
unsigned long flags;
struct sk_buff_head *list = &sk->sk_receive_queue;
//接收缓存用完
if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) {
atomic_inc(&sk->sk_drops);
trace_sock_rcvqueue_full(sk, skb);
return -ENOMEM;
}
//清除skb的入口设备描述符
skb->dev = NULL;
//skb由sock拥有
skb_set_owner_r(skb, sk);
skb_len = skb->len;
//接收队列锁
spin_lock_irqsave(&list->lock, flags);
skb->dropcount = atomic_read(&sk->sk_drops);
//将skb添加到sock->sk_receive_queue
__skb_queue_tail(list, skb);
spin_unlock_irqrestore(&list->lock, flags);
//在sock_init_data中初始化为sock_def_readable
sk->sk_data_ready(sk, skb_len);
return 0;
}
网络子系统82_inet协议族-SOCK_RAW(三)
最新推荐文章于 2025-06-13 21:43:04 发布