荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: 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软件 网络书店