《TCP/IP详解卷2:实现》笔记--BPF:BSD 分组过滤程序

BSD分组过滤程序(BPF)是一种软件设备,用于过滤网络接口的数据流,即给网络接口加上开关。应用进程打开/dev/bpf0、

/dev/bpf1等等后,可以读取BPF设备,每个应用进程一次只能打开一个BPF设备。

通过若干ioctl命令,可以配置BPF设备,把它与某个网络接口相关联,并安装过滤程序,从而能够选择性地接收输入的分组。

BPF设备打开后,应用进程通过读写设备来接收分组,或将分组放入网络接口队列中。

BPF设备工作的前提是网络接口必须能够支持BPF。之前提到的以太网和环回接口的驱动程序都调用了bpfattach,用于配置

读取BPF设备的接口。

1.bpf_if结构

BPF维护一个链表,包含所有支持BPF的网络接口,每个接口都有一个bpf_if结构描述,全局指针bpf_iflist指向表中的第一个

结构,下图给出了BPF接口结构。

bif_next指向链表中的下一个BPF接口结构。

bif_dlist指向另一个链表,包括所有已打开并配置过的BPF设备。

如果某个网络接口已配置了BPF设备,即被加上了开关,则bif_driverp为空。为某个网络接口配置BPF设备是时,*bif_driverp

将指向bif_if结构,从而告诉接口可以开始向BPF传递分组。

接口类型保存在bif_dlt中。下图列出了几个接口所对应的常量值。

下图给出了每个输入分组中附加的bpf_hdr结构。

bh_tstamp记录了分组被捕捉的时间。bh_caplen等于BPF保存的字节数,bh_datalen等于原始分组中的字节数。bh_headlen

等于bpf_hdr的大小加上所需填充字节的长度。它用于解释从BPF设备中读取的分组,应该等同于接收接口的bif_hdrlen。

BPF接收的所有分组都有一个附加的BPF首部。bif_hdrlen等于首部大小,最后,bif_ifp指向对应接口的ifnet结构。

下图给出了 bpf_if结构是如何与ifnet结构建立连接的。

注意:bif_driverp指向网络接口的if_bpf和sc_bpf指针,而不是接口结构。

按照各接口驱动程序调用bpfattach时给出的信息,对3个接口初始化链路类型和首部长度成员变量。每个设备驱动程序初始化

调用bpfattach时,将构建BPF接口结构链表。该函数的大概处理流程如下:

1.为bpf_if创建空间。

2.初始化bpf_if结构。

3.计算BPF首部大小。下图列出了前述3种接口上,各自捕捉到的BPF分组的总体结构。

4.初始化bpf_dtab表。

5.打印控制台信息。

2.dpf_d结构

为了能够选择性地接收输入报文,应用程序首先打开一个BPF设备,调用若干ictl命令规定BPF过滤程序的条件,指明接口、

读缓存大小和超时时限。每个BPF设备都有一个相关的bpf_d结构,如下图所示。

如果同一个网络接口上配置了多个BPF设备,与之相应的bpf_d结构将组成一个链表。bd_next指向链表中的下一个结构。

分组缓存:

每个bpf_d结构都有两个分组缓存,输入分组通常保存在bd_sbuf(存储缓存)所对应的缓存中,另一个缓存要么对应于bd_fbuf

(空闲缓存),意味着缓存为空,或者对应于bd_hbuf(暂留缓存),意味着缓存中有分组等待应用进程读取,bd_slen和bd_hlen

分别就了保存在存储缓存和暂留缓存中的字节数。

如果存储缓存已满,它将被连接到bd_hbuf,而空闲缓存将被连接到bd_sbuf。当暂留缓存清空时,它被连接到bd_fbuf。

bd_bufsize记录与设备相连的两个缓存的大小,其默认值等于4096字节。

bd_bif指向BPF设备对应的bpf_if结构。

bd_rtout是等待分组时,延迟的滴答数。

bd_filter指向BPF设备的过滤程序代码。

两个统计值,应用进程可通过BIOGSTATS读取,分别保存在bd_rcount和bd_dcount中。

bd_promisc通过BIOCPROMISC命令置位,从而使接口工作在混杂状态。

bd_state未使用。

bd_immediate通过BIOCIMMEDIATE命令置位,促使驱动程序收到分组后即返回,不在等待暂留缓存填满。

bd_pad填充bpf_d结构,从而与长字节边界对齐。

bd_sel保存的selinfo结构,可用于select系统调用。

2.1.bpfopen函数

应用进程调用open,视图打开一个BPF设备时,该调用将被转到bpfopen,该函数用于分配bpf_d结构。

2.2.bpfioctl函数

设备打开后,可通过ioctl命令进行配置,下图总结了与BPF设备有关的ioctl命令。

下图给出了打开第二个BPF设备,并连接到同一个以太网网络接口后的各结构变量的状态。

连接到以太网接口的BPF设备:

连接到以太网接口的两个BPF设备:

第二个BPF设备打开时,在bpf_dtab表中分配一个新的dpf_d结构。

2.3.bpf_setif函数

bpf_setif函数,负责建立BPF描述符与网络接口间的连接,大概流程如下:

1.寻找匹配的ifnet结构。

2.连接bpf_d结构。

2.4.bpf_attachd函数

该函数建立起BPF描述符与BPF设备和网络接口间的对应关系。

3.BPF输入

一旦BPF设备打开并配置完成,应用进程就通过read系统调用从接口中接收分组。BPF过滤程序复制输入分组,因此不会

干扰正常的网络处理。输入分组保存在于BPF设备连接的存储缓存和暂留缓存中。

3.1.bpf_tap函数

下面列出了LANCE设备驱动程序调用bpf_tap的代码:

bpf_tap(le->sc_if.if_bpf, buf, len + sizeof(struct ether_header));

在该函数中,for循环遍历连接到的网络接口的BPF设备链表。对于每个设备,分组被递交给bpf_filter。如果过滤程序接受了

分组,它返回捕捉的字节数,并调用catchpacket复制分组。如果过滤程序拒绝了分组,长度等于0,循环继续。

3.2.catchpacket函数

该函数的大概处理流程如下:

1.判断分组是否放入缓存。如果空闲缓存可用,则轮转缓存,并通过bpf_wakeup唤醒所有等待输入数据的应用程序。

2.立即方式处理。如果设备处于立即方式,则唤醒所有等待进程以处理进入分组--内核中没有分组的缓存。

3.添加BPF首部。

3.3.bpfread函数

内核把针对BPF设备的read转交给bpfread处理。该函数的大概处理流程如下:

1.等待数据。因为多个应用进程能够从同一个BPF设备中读取数据,如果有某个进程已先读取了数据,while循环将强迫读

操作继续。如果暂留缓存中存在数据,循环被跳过。这与两个应用进程通过两个不同的BPF设备过滤同一个网络接口的情况

是不同的。

2.立即方式。如果设备处于立即方式,且存储缓存中有数据,则轮回缓存,while循环被终止。

3.无可用的分组。如果设备不处于立即方式,或者存储缓存中没有数据,则应用程序进入休眠状态,直到某个信号到达。

4.查看暂留缓存。如果定时器超时,且暂留缓存中存在数据,则循环终止。

5.查看存储缓存。如果定时器超时,且存储缓存中没有数据,则read返回0.应用进程执行限时读取时,必须考虑到这种情况。

如果定时器超时,且存储缓存中存在数据,则把存储缓存转给暂留缓存,循环终止。

6.分组可用。从暂留缓存中移出相应的字节,交给应用程序,把暂留缓存转给空闲缓存,清除缓存计数器,函数返回。

时间: 2024-10-21 06:54:10

《TCP/IP详解卷2:实现》笔记--BPF:BSD 分组过滤程序的相关文章

《TCP/IP详解卷1:协议》第14章 DNS:域名系统---读书笔记

<TCP/IP详解卷1:协议>第14章 DNS:域名系统---读书笔记 1.引言 5.指针查询 DNS中一直难于理解的部分就是指针查询方式,即给定一个IP地址,返回与该地址对应的域名. 当一个组织加入Internet,并获得DNS域名空间的授权,如noao.edu,则它们也获得了对应IP地址的in-addr.arpa域名空间的授权.在noao.edu这个例子中,它的网络号是140.252的B类网络.在DNS树中结点in-addr.arpa的下一级必须是该IP地址的第一字节(例中为140),再下

《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(2)-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 <TCP/IP详解卷1:协

《TCP/IP详解卷1:协议》第5章 RARP:逆地址解析协议-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 1.引言 具有本地磁盘的系统引导

《TCP/IP详解卷1:协议》第3章 IP:网际协议(1)-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 1.引言 IP是TCP/IP协议族中最核心的协议.所有的TCP.UDP.ICMP及IGMP数据都以IP数据报格式传输.IP提供不可靠.无连接的数据报传送服务. (1)不可靠 它不能保证IP数据报能成功地到达目的地.IP仅提供最好的传输服务.如果发生某种错误,如某个路由器暂时用完了缓冲区,IP有一个简单的错误处理算法:丢弃该数据报,然后发送ICMP消息报给信源端.

《TCP/IP详解卷2:实现》笔记--IP的分片和重装

IP首部内有三个字段实现分片和重装:标识字段(ip_id).标志字段(ip_off的3个高位比特)和偏移字段(ip_off的13个低位 比特).标志字段由3个1bit标志组成.比特0是保留的必须为0,:比特1是"不分片"(DF)标志:比特2是"更多分片"(MF)标志. Net/3中,标志和偏移字段结合起来,由ip_off访问,如下图所示: ip_off的其他13bit指出在原始数据报内分片的位置,以8字节为单位计算.因此,除最后一个分片外,其他的分片都希望是一个 8

《TCP/IP详解卷2:实现》笔记--域和协议

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">Net/3组把协议关联到一个域,并且用一个协议族常量来标识每个域.Net/3还通过所有的编址方法将协议分组.在一个域中</span> 的每个协议使用同类地址,并且每种地址只被一个域使用.作为结果,一个域能通过它的协议族或地址族常量唯一标识. 下图是是我们讨论的协议和常量. 1

《TCP/IP详解卷2:实现》笔记--IP编址

1.接口和地址 在本文中讨论的所有接口和地址结构的一个例子配置如下图所示: 上图中显示了我们三个接口例子:以太网接口,SLIP接口和环回接口.它们都有一个链路层地址作为地址列表中的第一个结点. 显示的以太网接口有两个IP地址,SLIP接口有一个IP地址,并且环回接口有一个IP地址和一个OSI地址. 所有的IP地址都被链接到in_ifaddr列表中,并且所有链路层地址能从ifnet_addrs数组访问. 后面的部分讨论上图的数据结构以及用来查看和修改这些结构的IP专用ioctl命令. 2.sock

《TCP/IP详解卷2:实现》笔记--接口层

提示:该实验所在的平台是在RedHat 6下 该实验成功的前提有三个: (1):windows能ping通linux系统 (2):关闭linux的防火墙 :执行指令 /etc/init.d/iptables  stop (3):让SeLinux关闭  :执行指令:  setenforce permissive 补充: SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,是 Linux历史上最杰出的新安全子系统.SELinux 是一个

《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(1)-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 <TCP/IP详解卷1:协

《TCP/IP详解卷1:协议》第6章 ICMP:Internet控制报文协议-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 <TCP/IP详解卷1:协