IP转发和本地传递

转发步骤:

  1. 处理IP选项。这可能会涉及记录本地IP地址以及时间戳(如果IP报头中的选项需要这两项信息)
  2. 确定封包可以被转发(根据IP报头字段)
  3. 递减IP报头的TTL字段,然后,如果TTL字段变为零,就丢弃该封包
  4. 根据路径相关MTU,必要时处理分段工作
  5. 把封包传送至外出设备

如果封包因为某种原因而无法转发,源主机就必须受到ICMP消息,来说明碰到的问题。即使封包会被转发,但是封包绕送时使用的是次佳路径,因而触发了重导向事件时,ICMP消息也会送出,来作为通知。

ip_forward函数:

   1:  int ip_forward(struct sk_buff *skb)
   2:  {
   3:      struct iphdr *iph;    /* Our header */
   4:      struct rtable *rt;    /* Route we use */
   5:      struct ip_options * opt    = &(IPCB(skb)->opt);
   6:   
   7:      if (skb_warn_if_lro(skb))
   8:          goto drop;
   9:   
  10:      if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb))
  11:          goto drop;
  12:   
  13:      if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
  14:          return NET_RX_SUCCESS;
  15:   
  16:      if (skb->pkt_type != PACKET_HOST)
  17:          goto drop;
  18:   
  19:      skb_forward_csum(skb);
  20:   
  21:      /*
  22:       *    According to the RFC, we must first decrease the TTL field. If
  23:       *    that reaches zero, we must reply an ICMP control message telling
  24:       *    that the packet's lifetime expired.
  25:       */
  26:      if (ip_hdr(skb)->ttl <= 1)
  27:          goto too_many_hops;
  28:   
  29:      if (!xfrm4_route_forward(skb))
  30:          goto drop;
  31:   
  32:      rt = skb_rtable(skb);
  33:   
  34:      if (opt->is_strictroute && opt->nexthop != rt->rt_gateway)
  35:          goto sr_failed;
  36:   
  37:      if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
  38:               (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
  39:          IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS);
  40:          icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
  41:                htonl(dst_mtu(&rt->dst)));
  42:          goto drop;
  43:      }
  44:   
  45:      /* We are about to mangle packet. Copy it! */
  46:      if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len))
  47:          goto drop;
  48:      iph = ip_hdr(skb);
  49:   
  50:      /* Decrease ttl after skb cow done */
  51:      ip_decrease_ttl(iph);
  52:   
  53:      /*
  54:       *    We now generate an ICMP HOST REDIRECT giving the route
  55:       *    we calculated.
  56:       */
  57:      if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb))
  58:          ip_rt_send_redirect(skb);
  59:   
  60:      skb->priority = rt_tos2priority(iph->tos);
  61:   
  62:      return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev,
  63:                 rt->dst.dev, ip_forward_finish);
  64:   
  65:  sr_failed:
  66:      /*
  67:       *    Strict routing permits no gatewaying
  68:       */
  69:       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
  70:       goto drop;
  71:   
  72:  too_many_hops:
  73:      /* Tell the sender its packet died... */
  74:      IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_INHDRERRORS);
  75:      icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
  76:  drop:
  77:      kfree_skb(skb);
  78:      return NET_RX_DROP;
  79:  }

ip_forward_finish函数:

   1:  static int ip_forward_finish(struct sk_buff *skb)
   2:  {
   3:      struct ip_options * opt    = &(IPCB(skb)->opt);
   4:   
   5:      IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
   6:   
   7:      if (unlikely(opt->optlen))
   8:          ip_forward_options(skb);
   9:   
  10:      return dst_output(skb);
  11:  }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值