网络子系统46_ip协议数据帧的转发

简介:
//	ip协议数据转发
//		ip_forward以回调函数的形式,保存在skb->dst->input,skb->dst在ip_route_input路由封包时被设置
//	调用路径:ip_rcv->ip_rcv_finish->dst_input->(skb->dst->input)

//	函数的主要任务:
//		1.递减ttl
//		2.如果路由被重定向,则向发送方发送icmp重定向报文
//		2.如果有选项,通过ip_forward_options处理在转发时需要更新的选项
//		3.通过ip_output,将报文传递到ip发送路径上
1.1 int ip_forward(struct sk_buff *skb)
{
	struct iphdr *iph;	
	struct rtable *rt;	
	struct ip_options * opt	= &(IPCB(skb)->opt);//ip协议控制块,由ip_options_compile初始化

	//XFRM是 Linux 2.6 内核为安全处理引入的一个可扩展功能框架
	if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb))
		goto drop;
	//
	if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))//对router alert选项的处理
		return NET_RX_SUCCESS;

	if (skb->pkt_type != PACKET_HOST)//重复检查,l2地址非本机,直接丢弃
		goto drop;

	skb->ip_summed = CHECKSUM_NONE;//需要软件重新计算校验和
	
	iph = skb->nh.iph;

	if (iph->ttl <= 1)//数据帧到期
                goto too_many_hops;
    //XFRM路由
	if (!xfrm4_route_forward(skb))
		goto drop;

	iph = skb->nh.iph;
	rt = (struct rtable*)skb->dst;
	//处理严源路由选项
	//	rt->rt_dst 目的ip地址
	//	rt->rt_gateway 当目的主机直连时,rt_gateway匹配目的地址,当需要通过网关到达目的地址时,rt_gateway设置为下一条网关
	//	skb->dst在ip_options_rcv_srr中,使用选项中指定的ip地址作为目标地址,通过路由查找,设置为第一个非本机ip的单播路由项
	if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)//由于是严源路由选项,因此下一跳地址,必须等于源路由选项中列出的地址
		goto sr_failed;

	if (skb_cow(skb, LL_RESERVED_SPACE(rt->u.dst.dev)+rt->u.dst.header_len))//检查skb是否被共享,如果被共享的话,拷贝一份,并在头部预留l3+l2
		goto drop;
	iph = skb->nh.iph;
	//递减跳数
	ip_decrease_ttl(iph);
	//RTCF_DOREDIRECT在ip_route_input_slow中被设置,表示ICMP_REDIRECT必须被送回源地址
	if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr)
		ip_rt_send_redirect(skb);

	skb->priority = rt_tos2priority(iph->tos);//通过tos字段计算skb在规则队列中的优先级

	return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev,
		       ip_forward_finish);

sr_failed:

         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
         goto drop;

too_many_hops:
        icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
drop:
	kfree_skb(skb);
	return NET_RX_DROP;
}

//	将转发数据传递到发送路径上

//	调用路径:ip_forward->netfilter hooks->ip_forward_finish
1.2 static inline int ip_forward_finish(struct sk_buff *skb)
{
	struct ip_options * opt	= &(IPCB(skb)->opt);

	IP_INC_STATS_BH(IPSTATS_MIB_OUTFORWDATAGRAMS);

	if (unlikely(opt->optlen))
		ip_forward_options(skb);//处理宽松路由选项和time stamp选项

	return dst_output(skb);//调用ip_output
}
//	数据转发时更新的选项
//		1.record route选项
//		2.源路由选项
//		3.time stamp选项
1.3 void ip_forward_options(struct sk_buff *skb)
{
	struct   ip_options * opt	= &(IPCB(skb)->opt);
	unsigned char * optptr;
	struct rtable *rt = (struct rtable*)skb->dst;
	unsigned char *raw = skb->nh.raw;
	//record route选项
	if (opt->rr_needaddr) {//说明为出口skb,因为入口skb在ip_options_compile已经被使用首选源地址填写
		optptr = (unsigned char *)raw + opt->rr;
		ip_rt_get_source(&optptr[optptr[2]-5], rt);
		opt->is_changed = 1;
	}
	if (opt->srr_is_hit) {//表示在源路由选项列表中,有可用的下一跳ip地址
		int srrptr, srrspace;

		optptr = raw + opt->srr;

		for ( srrptr=optptr[2], srrspace = optptr[1];
		     srrptr <= srrspace;
		     srrptr += 4
		     ) {
			if (srrptr + 3 > srrspace)
				break;
			if (memcmp(&rt->rt_dst, &optptr[srrptr-1], 4) == 0)//下一跳地址在源路由地址列表中
				break;
		}
		if (srrptr + 3 <= srrspace) {//表示下一跳在源路由地址列表中
			opt->is_changed = 1;
			ip_rt_get_source(&optptr[srrptr-1], rt);
			skb->nh.iph->daddr = rt->rt_dst;//更新目的地址为下一跳的地址
			optptr[2] = srrptr+4;//更新选项的ptr[2]指针到下一跳
		} else if (net_ratelimit())
			printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");
		if (opt->ts_needaddr) {
			optptr = raw + opt->ts;
			ip_rt_get_source(&optptr[optptr[2]-9], rt);
			opt->is_changed = 1;
		}
	}
	if (opt->is_changed) {
		opt->is_changed = 0;
		ip_send_check(skb->nh.iph);//计算ip校验和
	}
}

目录
相关文章
|
3月前
|
数据采集 算法 数据挖掘
模块化控制协议(MCP)在网络中增强智能体执行效率的研究
随着Web3技术的迅速发展,去中心化应用和智能体在各种领域的应用逐渐增多。MCP(Modularized Control Protocol,模块化控制协议)作为一种增强智能体执行能力的关键技术,为Web3场景中的智能体提供了更强的灵活性和可扩展性。本文将探讨如何利用MCP技术提升智能体在Web3场景中的执行能力,并通过实例代码展示其实现路径。
314 22
|
7天前
|
网络协议 Linux 虚拟化
配置VM网络:如何设定静态IP以访问主机IP和互联网
以上就是设定虚拟机网络和静态IP地址的基本步骤。需要注意的是,这些步骤可能会因为虚拟机软件、操作系统以及网络环境的不同而有所差异。在进行设定时,应根据具体情况进行调整。
92 10
|
28天前
|
监控 负载均衡 安全
WebSocket网络编程深度实践:从协议原理到生产级应用
蒋星熠Jaxonic,技术宇宙中的星际旅人,以代码为舟、算法为帆,探索实时通信的无限可能。本文深入解析WebSocket协议原理、工程实践与架构设计,涵盖握手机制、心跳保活、集群部署、安全防护等核心内容,结合代码示例与架构图,助你构建稳定高效的实时应用,在二进制星河中谱写极客诗篇。
WebSocket网络编程深度实践:从协议原理到生产级应用
|
1月前
|
运维 架构师 安全
二层协议透明传输:让跨域二层协议“无感穿越”多服务商网络
简介:本文详解二层协议透明传输技术,适用于企业网工、运营商及架构师,解决LLDP/LACP/BPDU跨运营商传输难题,实现端到端协议透传,提升网络韧性与运维效率。
|
3月前
|
监控 安全 Go
使用Go语言构建网络IP层安全防护
在Go语言中构建网络IP层安全防护是一项需求明确的任务,考虑到高性能、并发和跨平台的优势,Go是构建此类安全系统的合适选择。通过紧密遵循上述步骤并结合最佳实践,可以构建一个强大的网络防护系统,以保障数字环境的安全完整。
110 12
|
5月前
|
安全 网络协议 Linux
Linux网络应用层协议展示:HTTP与HTTPS
此外,必须注意,从HTTP迁移到HTTPS是一项重要且必要的任务,因为这不仅关乎用户信息的安全,也有利于你的网站评级和粉丝的信心。在网络世界中,信息的安全就是一切,选择HTTPS,让您的网站更加安全,使您的用户满意,也使您感到满意。
169 18
|
4月前
|
监控 安全 网络安全
网络安全新姿势:多IP配置的五大好处
服务器配置多IP地址,既能提升网络速度与安全性,又能实现多站点托管和故障转移。本文详解多IP的五大妙用、配置方法及进阶技巧。从理论到实践,合理规划IP资源,让服务器性能跃升新高度。
155 2
|
6月前
|
网络协议 数据安全/隐私保护 网络架构
|
6月前
|
域名解析 API PHP
VM虚拟机全版本网盘+免费本地网络穿透端口映射实时同步动态家庭IP教程
本文介绍了如何通过网络穿透技术让公网直接访问家庭电脑,充分发挥本地硬件性能。相比第三方服务受限于转发带宽,此方法利用自家宽带实现更高效率。文章详细讲解了端口映射教程,包括不同网络环境(仅光猫、光猫+路由器)下的设置步骤,并提供实时同步动态IP的两种方案:自建服务器或使用三方API接口。最后附上VM虚拟机全版本下载链接,便于用户在穿透后将服务运行于虚拟环境中,提升安全性与适用性。

热门文章

最新文章