第二十章:因特网协议第四版(IPv4):转发和本地传递
在ip_rcv_finish函数的尾端,如果目的地址和本地接口不同,内核必须把封包转发至适当的主机,若目的地址是本地地址,内核必须把封包准备好,以便高层使用。本章主要介绍转发和本地传递是怎么完成的。
转发:
转发的工作由ip_forward函数和ip_forward_finish完成。此时,ip_rcv_finish里已经调用了ip_route_input,所以skb_buff中已经包含了转发封包所需要的所有信息。转发由下列步骤组成:
处理IP选项。
确定封包可以被转发。
递减IP报头的TTL字段。
根据路径相关MTU,必要时处理分片工作。
把封包传送至外出设备。
如果封包无法转发会发送ICMP,或者被转发了,但使用的是次佳路由,因而触发了重导项事件,发送ICMP来通知重导项事件。
和IPsec交互也是转发工作的一部分,由xfrm4_xxx函数实现,这些函数是进入IPsec基础架构的钩子。本书不会讨论IPsec,就是说后续讨论假设IPsec没有配置。
ip_forward函数:
原型:int ip_forward(struct sk_buff *skb);
如果报头中发现了Router Alert选项,则封包现在就会被处理。处理函数ip_call_ra_chain会先重组整个ip封包,然后把封包传给那些Raw套接字(这些套接字设置了IP_ROUTER_ALERT)。然后ip_forward直接返回。
如果报头中没有Router Alert选项,或者存在但没有感兴趣的程序在运行,ip_forward会继续下去:
if(IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb) )
return NET_RX_SUCCESS;
if(skb->pkt_type != PACKET_HOST)
goto drop;
skb->ip_summed = CHECKSUM_NONE;//转发封包,不涉及L4,所以用CHECKSUM_NONE指出当前校验和无误,若有些处理工作修改了IP报头,TCP报头或有效载荷,那么在传输前,内核就会重算校验和。
真实的转发流程是由递减TTL字段开始的:
if(iph->ttl <= 1)
goto too_many_hops;
如果IP报头包含一个Strict Source Route选项,且下个跳点和路由子系统找到的不一样,则Source Routing选项失败了,丢弃该封包,发送一个ICMP报文给传送者。
rt = (struct rtable *)skb->dst;
if(opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
goto sr_failed;
多数健康检查做完后,此函数会更新报头,所以需要拷贝缓冲区。
if(skb_cow(skb,LL_RESERVED_SAPCE(rt->u.dst.dev)+rt->udst.header_len))
goto drop;
现在,TTL会由ip_decrease_ttl递减,并且该函数还会更新ip校验和:
ip_decrease_ttl(iph);
如果有比请求的还要更好的下一跳点存在,原来的主机就会收到ICMP REDIRECT 消息(前提是原来的主机没有请求源路由之时??这里怎么理解?)。
if(rt->rt_flags & RTCF_DOREDIRECT && !opt->ssr)
ip_rt_send_redirect(skb);
这里,priority字段是使用ip头的TOS字段设定的,由Traffic Control(Qos层)使用。
skb->priority = rt_tos2priority(iph->tos);
最后,ip_forward函数会要求Netfilter执行ip_forward_finish(如果没有禁止转发的规则)
return NF_HOOK(PF_INET,NF_IP_FORWARD,skb,skb->dev,rt->u.dst.dev,ip_forward_finish);
ip_forward_finish函数:
到了这一步,说明封包已经通过所有会使其停止的检查,而且真的已经就绪,可以传输到另一个系统了。
先前在ip_forward函数中已经处理过Route Alert和Strict Source Routing选项了(还有其他选项,只是列举了这两个例子而已)。ip_forward_finish会调用ip_forward_options来处理那些选项所需的最后工作。最后,ip_forward_finish函数会调用dst_output函数将封包传递出去。
dst_output函数:
无论是本地产生还是转发,所有传输都会通过dst_output上路。此时,IP报头已经完成,内含传输所需信息以及本地系统负责添加的其他任何信息。dst_output函数会调用虚拟函数output,分段也是在该函数内部处理的。最后,会调用ip_finish_output来衔接邻居子系统,只有当Netfilter放行时,ip_finish_output才会被调用,否则丢弃封包。
static inline int dst_out(struct sk_buff *skb)
{
int err;
for(; ;){
err = skb->dst->output(&skb);
if(likely(err = 0))
return err;
if(unlikely(err != NET_XMIT_BYPASS))
return err;
}
}
本地传递:
第三十五章会说明转发(路由)引擎如何得知本地主机是封包的地址。当封包抵达目的主机时,ip_rcv_finish开端调用ip_route_input,就会把skb->dst->input初始化为ip_local_deliver。此外,Netfilter有最后的权力决定do_something函数是否可以调用相应的do_something_finish函数。
int ip_local_deliver(struct sk_buff *skb)
{
if(skb->nh.iph->frag_off & htons(IP_MF | IP_OFFSET)){
skb = ip_defrag(skb,IP_DEFRAG_LOCAL_DELIVER);//转发几乎不需要重组,而本地传递必须重组整个ip封包
if(!skb)
return 0;
}
return NF_HOOK(PF_INET,NF_IP_LOCAL_IN,skb,skb->dev,rt->u.dst.dev,ip_local_deliver_finish); //第二十四章会谈论ip_local_deliver_finish函数的细节
}
第二十章:因特网协议第四版(IPv4):转发和本地传递相关推荐
- 深入理解Linux网络技术内幕学习笔记第十九章:因特网协议第四版(IPv4):Linux的原理和功能
本章主要介绍Linux支持IP的数据结构和基本活动,如入口IP包如何传递至IP接收函数,校验和如何验证,以及IP选项如何处理. 主要的IPv4数据结构: struct iphdr{ };//ip报头 ...
- 计算机操作系统 (第四版汤小丹老师) 复习笔记第一章
教材为西安电子科技大学 汤小丹老师 第四版 1.1操作系统目标和作用 1.目标 目前存在着多种类型的OS,不同类型的OS,其目标各有所侧重.通常在计算机硬件上配置的OS,其目标有以下几点: 方便性 便 ...
- Algorithms, 4th Edition(算法-第四版)源码使用系统配置
关于-Algorithms, 4th Edition (算法-第四版)源代码在本地机器的运行配置. 其实关于这个教程的使用已经在 Java Algorithms and Clients 页面中写出,并 ...
- JavaScript高级程序设计第四版学习--第二十四章
title: JavaScript高级程序设计第四版学习–第二十四章 date: 2021-5-31 10:46:01 author: Xilong88 tags: JavaScript 本章内容: ...
- 互联网协议 — IPv4 互联网协议第 4 版
目录 文章目录 目录 IPv4 IPv4 的报文格式 IPv4 Header IPv4 的地址 IPv4 的子网划分 子网掩码 IPv4 IPv4(Internet Protocol Version ...
- 《汇编语言》王爽(第四版) 第十章 实验10
文章目录 前言 一.子程序1 显示字符串 1.实验任务 2.分析 (1)如何在指定位置显示 (2)如何显示指定颜色 (3)保存子程序中用到的寄存器 3.代码 二.子程序2 解决除法溢出的问题 1.实验 ...
- 现代操作系统英文第四版课后习题答案——第二章
@T现代操作系统第四版参考答案 现代操作系统英文第四版第二章参考答案--进程 先更新第二章的答案,习惯中文的童鞋请左转百度翻译 Solution for chapter 2 The transitio ...
- 机器人导论(第四版)学习笔记——第二章
机器人学导论(第四版)学习笔记--第二章 2. 空间描述和变换 2.1 引言 2.2 描述:位置.姿态与位姿 2.3 映射:从一个坐标系到另一个坐标系的变换 2.4 算子:平行,旋转和变换 2.5 总 ...
- 汇编语言 王爽 第四版 第二章 检测点2.2
汇编语言 王爽 第四版 课后检测点 课后实验 持续更新~~ 检测点2.2 给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为 0010H 到 1000FH . 最小肯定是偏移地址为0, ...
最新文章
- centos7 安装jdk7
- 系统监控:top vs Htop vs Glances
- Linux2.6内核--中断线被关闭的情况
- python用pil图像放大缩小_python使用PIL缩放网络图片并保存的方法
- 【Python】分享几个好用到爆的Python内置模块
- ASP.NET Core Web API 与 SSL
- 缺失的第一个正数—leetcode41
- cad插件制作教程_CAD电子签名制作教程
- Python实战从入门到精通第十一讲——可接受任意数量参数的函数
- lesson 2.4 - Converting MEL Commands to Python
- INFORMATION_SESSION_VARIABLES feature is disabled问题
- 关于计算机信息管理的照片,2021年10月青海自考计算机科学与技术(计算机信息管理方向)专业报名照片要什么格式...
- 《中英文在自然语言处理上的十大差异点》学习总结
- 二维baker映射 matlab,基于Baker映射的混沌图像加密算法
- Open3d数据滤波和点云分割
- gcc用-O0优化无问题,-O3优化时程序崩溃的问题
- 【Android】HAL层浅析
- Qt windows下获取CPU、主板、硬盘、网卡等相关信息
- python nose
- 抓准痛点就能撬动市场!读屏时代的黑科技非它莫属了