L4协议和raw ip处理

L4协议的注册:

位于IPv4之上的L4协议是由net_protocol数据结构定义的

   1:  struct net_protocol {
   2:      int            (*handler)(struct sk_buff *skb);
   3:      void            (*err_handler)(struct sk_buff *skb, u32 info);
   4:      int            (*gso_send_check)(struct sk_buff *skb);
   5:      struct sk_buff           *(*gso_segment)(struct sk_buff *skb,
   6:                             int features);
   7:      struct sk_buff          **(*gro_receive)(struct sk_buff **head,
   8:                             struct sk_buff *skb);
   9:      int            (*gro_complete)(struct sk_buff *skb);
  10:      unsigned int        no_policy:1,
  11:                  netns_ok:1;
  12:  };

handler,由此协议注册的函数,来作为送进来的封包的处理函数。

err_handler,由icmp协议处理函数所用的函数,用于通知l4协议有关接收到icmp unreachable消息的时间。

no_policy,此字段在网络协议中的某些关键点都会被查询,用于使协议免于ipsec策略检查:1是指没有必要针对此协议检查ipsec策略。

   1:  /*
   2:   *    Add a protocol handler to the hash tables
   3:   */
   4:   
   5:  int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
   6:  {
   7:      int hash, ret;
   8:   
   9:      hash = protocol & (MAX_INET_PROTOS - 1);
  10:   
  11:      spin_lock_bh(&inet_proto_lock);
  12:      if (inet_protos[hash]) {
  13:          ret = -1;
  14:      } else {
  15:          inet_protos[hash] = prot;
  16:          ret = 0;
  17:      }
  18:      spin_unlock_bh(&inet_proto_lock);
  19:   
  20:      return ret;
  21:  }
  22:   
  23:  /*
  24:   *    Remove a protocol from the hash tables.
  25:   */
  26:   
  27:  int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
  28:  {
  29:      int hash, ret;
  30:   
  31:      hash = protocol & (MAX_INET_PROTOS - 1);
  32:   
  33:      spin_lock_bh(&inet_proto_lock);
  34:      if (inet_protos[hash] == prot) {
  35:          inet_protos[hash] = NULL;
  36:          ret = 0;
  37:      } else {
  38:          ret = -1;
  39:      }
  40:      spin_unlock_bh(&inet_proto_lock);
  41:   
  42:      synchronize_net();
  43:   
  44:      return ret;
  45:  }
 
L3到L4的传递:ip_local_deliver_finish
   1:  static int ip_local_deliver_finish(struct sk_buff *skb)
   2:  {
   3:      struct net *net = dev_net(skb->dev);
   4:   
   5:      __skb_pull(skb, ip_hdrlen(skb));
   6:   
   7:      /* Point into the IP datagram, just past the header. */
   8:      skb_reset_transport_header(skb);
   9:   
  10:      rcu_read_lock();
  11:      {
  12:          int protocol = ip_hdr(skb)->protocol;
  13:          int hash, raw;
  14:          const struct net_protocol *ipprot;
  15:   
  16:      resubmit:
  17:          raw = raw_local_deliver(skb, protocol);
  18:   
  19:          hash = protocol & (MAX_INET_PROTOS - 1);
  20:          ipprot = rcu_dereference(inet_protos[hash]);
  21:          if (ipprot != NULL) {
  22:              int ret;
  23:   
  24:              if (!net_eq(net, &init_net) && !ipprot->netns_ok) {
  25:                  if (net_ratelimit())
  26:                      printk("%s: proto %d isn't netns-ready\n",
  27:                          __func__, protocol);
  28:                  kfree_skb(skb);
  29:                  goto out;
  30:              }
  31:   
  32:              if (!ipprot->no_policy) {
  33:                  if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
  34:                      kfree_skb(skb);
  35:                      goto out;
  36:                  }
  37:                  nf_reset(skb);
  38:              }
  39:              ret = ipprot->handler(skb);
  40:              if (ret < 0) {
  41:                  protocol = -ret;
  42:                  goto resubmit;
  43:              }
  44:              IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
  45:          } else {
  46:              if (!raw) {
  47:                  if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
  48:                      IP_INC_STATS_BH(net, IPSTATS_MIB_INUNKNOWNPROTOS);
  49:                      icmp_send(skb, ICMP_DEST_UNREACH,
  50:                            ICMP_PROT_UNREACH, 0);
  51:                  }
  52:              } else
  53:                  IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
  54:              kfree_skb(skb);
  55:          }
  56:      }
  57:   out:
  58:      rcu_read_unlock();
  59:   
  60:      return 0;
  61:  }

转载于:https://my.oschina.net/longscu/blog/60642

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值