- /* 如果忽略掉原始套接字和IPSec,则该函数仅仅是根据IP头部中的协议字段选择上层L4协议,并交给它来处理*/
- static int ip_local_deliver_finish(struct sk_buff *skb)
- {
- /* 跳过IP头部 */
- __skb_pull(skb, ip_hdrlen(skb));
- /* Point into the IP datagram, just past the header. */
- /* 设置传输层头部位置 */
- skb_reset_transport_header(skb);
- rcu_read_lock();
- {
- /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */
- int protocol = ip_hdr(skb)->protocol;
- int hash;
- struct sock *raw_sk;
- struct net_protocol *ipprot;
- resubmit:
- /* 这个hash根本不是哈希值,仅仅只是inet_protos数组中的下表而已 */
- hash = protocol & (MAX_INET_PROTOS - 1);
- raw_sk = sk_head(&raw_v4_htable[hash]);
- /* 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))
- raw_sk = NULL;
- /* 查找注册的L4层协议处理结构。 */
- if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
- int ret;
- /* 启用了安全策略,则交给IPSec */
- if (!ipprot->no_policy) {
- if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- kfree_skb(skb);
- goto out;
- }
- nf_reset(skb);
- }
- /* 调用L4层协议处理函数 */
- /* 通常会是tcp_v4_rcv, udp_rcv, icmp_rcv和igmp_rcv */
- /* 如果注册了其他的L4层协议处理,则会进行相应的调用。 */
- ret = ipprot->handler(skb);
- if (ret < 0) {
- protocol = -ret;
- goto resubmit;
- }
- IP_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
- } else {
- if (!raw_sk) { /* 无原始套接字,提交给IPSec */
- if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- IP_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS);
- icmp_send(skb, ICMP_DEST_UNREACH,
- ICMP_PROT_UNREACH, 0);
- }
- } else
- IP_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
- kfree_skb(skb);
- }
- }
- out:
- rcu_read_unlock();
- return 0;
- }
linux TCP/IP协议栈 ---ip_local_deliver_finish()
订阅:
博文评论 (Atom)
没有评论:
发表评论