ip层和4层的接口实现分析
2009-09-10 00:00:00 来源:WEB开发网Java代码
static int ip_local_deliver_finish(struct sk_buff *skb)
{
///取出相应的net信息.
struct net *net = dev_net(skb->dev);
///下面两个主要是调整data指针,使data指针指向4层的数据开始处.
__skb_pull(skb, ip_hdrlen(skb));
skb_reset_transport_header(skb);
///加rcu锁.
rcu_read_lock();
{
///取出ip头中的协议.
int protocol = ip_hdr(skb)->protocol;
int hash, raw;
struct net_protocol *ipprot;
resubmit:
///得到raw socket, 如果不是raw socket,则返回0.
raw = raw_local_deliver(skb, protocol);
///计算4层协议的slot.
hash = protocol & (MAX_INET_PROTOS - 1);
///rcu读取相应的协议处理结构.
ipprot = rcu_dereference(inet_protos[hash]);
///主要是ipprot是否有被当前主机注册.
if (ipprot != NULL && (net == &init_net || ipprot->netns_ok)) {
int ret;
///判断ipsec,并进行相关处理.
if (!ipprot->no_policy) {
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
kfree_skb(skb);
goto out;
}
nf_reset(skb);
}
///调用handler,进入相应的4层协议的处理.
ret = ipprot->handler(skb);
if (ret < 0) {
protocol = -ret;
goto resubmit;
}
IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
}
................................................
out:
rcu_read_unlock();
return 0;
}
最后来看一下raw socket的处理,通过上面我们知道,会调用raw_local_deliver来进行raw socket的相关处理(如果没有raw socket,则会直接返回):
当应用程序使用raw ip socket,他只需要攒递给内核协议id(4层的协议),以及目的地址.因此这里存取sock的hash表使用的key就是4层协议id.
Java代码
///相应的hash表,保存raw socket.
struct raw_hashinfo {
rwlock_t lock;
struct hlist_head ht[RAW_HTABLE_SIZE];
};
static struct raw_hashinfo raw_v4_hashinfo = {
.lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
};
int raw_local_deliver(struct sk_buff *skb, int protocol)
{
int hash;
struct sock *raw_sk;
///通过协议计算hash值(使用4层协议id).
hash = protocol & (RAW_HTABLE_SIZE - 1);
///得到相应的raw_sk.
raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
/* If there maybe a raw socket we must check - if not we
* don't care less
*/
///交给raw socket的处理函数,raw_v4_input中会clone一个skb,然后交给最后的raw_rev函数去处理最终的数据包.
if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash))
raw_sk = NULL;
return raw_sk != NULL;
}
更多精彩
赞助商链接