荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: jjk (UNIX+C+XML+?? 傻了?), 信区: Linux
标  题: IP的转发函数分析(转寄)
发信站: 荔园晨风BBS站 (Mon Apr 22 19:48:55 2002), 转信

【 以下文字转载自 jjk 的信箱 】
【 原文由 jjk.bbs@apue.dhs.org 所发表 】
发信人: tl (tl), 信区: UKP
标  题: IP的转发函数分析
发信站: UNIX编程 (2002年04月16日20:57:48 星期二), 转信

作者:硅谷农民<mailto: ggnm@kerneldiary.net>

 int ip_forward(struct sk_buff *skb)
    当系统的路由处理完一个网络包的时候,如果就决定需要经由另外的网卡设备,转
发这个包到另外的子网,
    则调用ip_forward。
实现过程:
 * 在调用ip_forward之前,系统已经调用ip_route_input_slow找到路由,放在skb->d
st中,这里将它取出来。
 * 检查IP头部的TTL(time to live)值,如果小于1的话,则将这个包扔掉,并且发回i
cmp错误信息,表示这个
  IP包在网络上传输时经过太多的节点。
 * 如果设置了路由限制选项,需要判断两个路由是不是匹配。
    iph = skb->nh.iph;
    rt = (struct rtable*)skb->dst;
    if (iph->ttl <= 1)
        goto too_many_hops;
    if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
        goto sr_failed;
 * 找出要转发的网卡设备和MTU。
 * 如果找到更好的路由的话,则发回一个ICMP重定向网络包,告诉发送者更好的路由。

 dev2 = rt->u.dst.dev;
 mtu = rt->u.dst.pmtu;
 /* We now generate an ICMP HOST REDIRECT giving the route we calculated.
*/
 if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr)
  ip_rt_send_redirect(skb);
 * 如果skb的headroom不够(一般要有16字节来存放ethernet头部),或者还有另外的
模块在处理这个skb,
  则调用skb_cow来创建一个新的足够长的skb,并且拷贝原来的所有数据。
 * 将TTL减1。
 * 如果skb中数据的长度大于MTU,并IP包被标为路由器“不能分块”(Don't Fragmen
t),则发回一个ICMP信息包,
   告诉发送方需要自己将IP包分为更小块再发送。
    /* We are about to mangle packet. Copy it! */
    if ((skb = skb_cow(skb, dev2->hard_header_len)) == NULL)
        return NET_RX_DROP;
    iph = skb->nh.iph;
    opt = &(IPCB(skb)->opt);
    /* Decrease ttl after skb cow done */
    ip_decrease_ttl(iph);
    /* We now may allocate a new buffer, and copy the datagram into it.
     * If the indicated interface is up and running, kick it.
     */
    if (skb->len > mtu && (ntohs(iph->frag_off) & IP_DF))
        goto frag_needed;
 * 调用netfilter框架中的挂钩函数(hook),一般是NAT和防火墙模块注册的处理流程

   处理完以后,如果这个网络包需要继续处理,则调用ip_forward_finish。
    return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev2,
        ip_forward_finish);
----------------------------------------------------------------------------
---
static inline int ip_forward_finish(struct sk_buff *skb)
    当系统从ip_forward转入到netfilter的注册函数以后,再转回来调用ip_forward_
finish完成转发的功能。
实现过程:
 * 如果IP包的头部没有选项(option)的话,调用ip_forward_options处理。
 * 否则的话,直接调用ip_send将这个包转发出去。
    if (opt->optlen == 0) {
        return (ip_send(skb));
    }
    ip_forward_options(skb);
    return (ip_send(skb));

--

    欲慰韶华携吴钩,剑雪刀霜遣风流。
    一蓑烟雨平生事,道无狂嚣亦无愁!

※ 来源:·UNIX编程 apue.dhs.org·[FROM: 166.111.160.6] --
※ 转寄:·UNIX编程 apue.dhs.org·[FROM: 210.39.3.50]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店