//在函数ip_route_input_slow->ip_mkroute_input注册,
/*
* IP数据包的转发是由ip_forward()处理,该函数在ip_rcv_finish()
* 通过输入路由缓存被调用。
*/
int ip_forward(struct sk_buff *skb)
{
u32 mtu;
struct iphdr *iph; /* Our header */
struct rtable *rt; /* Route we use */
struct ip_options *opt = &(IPCB(skb)->opt);
struct net *net;
/\* that should never happen \*/
if (skb->pkt\_type != PACKET\_HOST)
goto drop;
if (unlikely(skb->sk))
goto drop;
if (skb\_warn\_if\_lro(skb))
goto drop;
if (!xfrm4\_policy\_check(NULL, XFRM\_POLICY\_FWD, skb))/\*查找ipsec 策略路由\*/
goto drop;
if (IPCB(skb)->opt.router\_alert && ip\_call\_ra\_chain(skb))//存在路由警告选项
return NET\_RX\_SUCCESS;
skb\_forward\_csum(skb);
net = dev\_net(skb->dev);
/\*
\* According to the RFC, we must first decrease the TTL field. If
\* that reaches zero, we must reply an ICMP control message telling
\* that the packet's lifetime expired.
\*/
if (ip\_hdr(skb)->ttl <= 1)//ttl 减少了
goto too\_many\_hops;
if (!xfrm4\_route\_forward(skb))//ipsec 策略路由转发处理
goto drop;
rt = skb\_rtable(skb);
if (opt->is\_strictroute && rt->rt\_uses\_gateway)//如果数据包启用了严格路由处理,且下一跳不是网关
goto sr\_failed;//发送ICMP\_SR\_FAILED icmp
IPCB(skb)->flags |= IPSKB\_FORWARDED;
mtu = ip\_dst\_mtu\_maybe\_forward(&rt->dst, true);
if (ip\_exceeds\_mtu(skb, mtu)) {
IP\_INC\_STATS(net, IPSTATS\_MIB\_FRAGFAILS);
icmp\_send(skb, ICMP\_DEST\_UNREACH, ICMP\_FRAG\_NEEDED,
htonl(mtu));
goto drop;
}
/\* We are about to mangle packet. Copy it! 确保空间足够\*/
if (skb\_cow(skb, LL\_RESERVED\_SPACE(rt->dst.dev)+rt->dst.header\_len))
goto drop;
iph = ip\_hdr(skb);
/\* Decrease ttl after skb cow done \*/
ip\_decrease\_ttl(iph);
/\*
\* We now generate an ICMP HOST REDIRECT giving the route
\* we calculated.
\*/
if (IPCB(skb)->flags & IPSKB\_DOREDIRECT && !opt->srr &&
!skb\_sec\_path(skb))
ip\_rt\_send\_redirect(skb);//数据报文输出路由存在重定向标志,且该数据报中不存在源路由选项,就发送重定向icmp报文
skb->priority = rt\_tos2priority(iph->tos);
return NF\_HOOK(NFPROTO\_IPV4, NF\_INET\_FORWARD,
net, NULL, skb, skb->dev, rt->dst.dev,
ip\_forward\_finish);
sr_failed:
/*
* Strict routing permits no gatewaying
*/
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
goto drop;
too_many_hops:
/* Tell the sender its packet died… */
__IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
drop:
kfree_skb(skb);
return NET_RX_DROP;
}
static int ip_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct ip_options *opt = &(IPCB(skb)->opt);
\_\_IP\_INC\_STATS(net, IPSTATS\_MIB\_OUTFORWDATAGRAMS);
\_\_IP\_ADD\_STATS(net, IPSTATS\_MIB\_OUTOCTETS, skb->len);
if (unlikely(opt->optlen))
ip\_forward\_options(skb);//IP数据报文选项 记录路由选项 时间戳等
return dst\_output(net, sk, skb);//指向ip\_output ip\_mc\_output
}
ip_forward
手机扫一扫
移动阅读更方便
你可能感兴趣的文章