Net/3中ARP的实现是和路由表紧密关联的,下图显示了我们描写ARP要用到的1个例子。
下面,我们扼要概述图中的有关要点。
1.llinfo_arp结构的双向链表包括了每个ARP已知的硬件地址的少许信息。同名全局变量llinfo_arp是该链表的头结点,图中
没有画出第1位la_prev指针指向最后1项,最后1项的la_next指针指向第1项。该链表由ARP时钟函数每一个5分钟处理1次。
2.每个已知硬件地址的IP地址都对应1个路由表结点(rtentry结构)。llinfo_arp结构的la_rt指针成员用来指向相应的rtentry
结构,一样地,rtentry结构的rt_llinfo指针成员指向llinfo_arp结构。
3.图中的最左侧第4个路由表结点则没有llinfo_arp结构,该结点对应于本地以太网(140.252.13.32)的路由项。该结点的
rt_flags中设置了C比特,表明该结点是被用来复制成其他结点的。
4.rtentry结构中的rt_gateway指针成员指向1个sockaddr_dl结构变量。如果保存物理地址长度的结构sdl_alen成员为6,那末
sockaddr_dl结构就包括相应的硬件地址信息。
5.路由结点变量的rt_ifp成员的相应指针指向对应网络装备接口的ifnet结构。中间的两个路由结点对应的是以太网上的其他主机,
这两个结点都指向le_softc[0]。而右侧的路由结点指向环回结构loif。由于rt_ifp.if_output指向输出函数,所以目的为本地的数据
报被路由至环回接口。
6.每个路由结点还有指向相应的in_ifaddr结构的指针变量。
7.la_hold成员是指向mbuf链表的指针。当要想某个IP传送数据报时,就需要广播1个ARP要求。当内核等待ARP回答时,存
放该待发数据报的mbuf链的头结点的地址信息就寄存在la_hold里。当收到ARP回答后,la_hold指向的mbuf链表中的IP数据
被发送出去。
8.路由表结点中rt_metric结构的变量rmx_expire寄存的是与对应ARP结点相干的定时信息,用来实现删除超时ARP结点。
下图显示了ARP函数与其他内核函数的关系。
在以太网中传送的ARP分组的格式以下图所示:
结构ether_header定义了以太网帧首部;结构arphdr定义了其后的5个字段,其信息用于在任何类型的介质上传送ARP要求
和回答;ether_arp结构除包括arphdr结构外,还包括源主机和目的主机的地址。
结构arphdr的定义以下图所示:
下图显示了ether_arp结构的定义,其中包括了arphdr结构、源主机和目的主机的IP地址和硬件地址。
每一个ARP结点中,都有1个llinfo_arp结构,所有这些结构组成的链表的头结点是作为全局变量分配的。我们常常把该链表
称为ARP高速缓存。
该双向链表的前两项是由insque和remque两个函数更新。
arpwhohas函数通常由arpresolve调用,用于广播1个ARP要求。它还可由每一个以太网装备驱动程序调用,在将IP地址赋予
该装备接口时主动发送1个地址联编信息(SIOCSIFADDR),主动发送地址联编信息不但可以检测在以太网中是不是存在IP
地址冲突,并可使其他机器更新其相应信息(免费ARP)。arpwhohas只是简单调用下arprequest函数。
arprequest函数由arpwhohas函数调用,用于广播1个ARP要求。该函数建立1个ARP分组,并将它传送到接口的输出函数。
下图显示了该函数建立的两个数据结构mbuf和sockaddr。另外还有两个函数中用到的指针eh和ea。
函数的大概处理流程以下:
1.分配和初始化mbuf。分配1个分组数据首部的吗mbuf,并对两个长度字段赋值。
2.初始化指针。给ea和eh两个指针赋值,并将ether_arp结构的值赋值为0。
3.填充以太网帧首部。目的以太网地址设为以太网广播地址,并将以太网帧类型设为ETHERTYPE_ARP。下图显示了不同
以太网帧类型字段的常量值。
4.填充ARP字段。填充ether_arp的所有字段,除ARP要求所要询问的目的硬件地址。
5.填充sockaddr,并调用接口输出函数。接口地址结构的sa_family成员的值设置为AP_UNSPEC,sa_number成员的值
设为16。调用接口输出函数ether_output。
当ether_input函数接收到帧类型字段为ETHERTYPE_ARP的以太网帧时,产生有限级为NETISR_ARP的软件中断,并将
该帧关在ARP输入队列arpintrq的后面。当内核处理该软件中断时,调用arpintr函数。
函数的大概处理流程是:
只有当帧的硬件类型指明为以太网地址,并且帧的长度大于或等于arphdr结构的长度加上两个硬件地址和两个协议地址的
长度时,该帧才能被处理。如果协议地址的类型是ETHERTYPE_IP或ETHERTYPE_IPTRAILERS时,调用in_arpinput函数,
否则该帧被抛弃。
该函数由arpintr调用,用于处理接收到的ARP要求/回答。ARP本身的概念比较简单,但是加上许多规则后,实现就比较
复杂,下面来看下两种典型的情况。
1.如果收到了1个针对本机IP地址的要求,则发送1个回答。这是1种普遍情况,很明显,我们将继续从那个主机收到
数据报,随后也会向它回送报文。所以,如果我们还没有对应它的ARP结点,就应当添加1个ARP结点,由于这时候我们
已知道对方的IP地址和硬件地址。
2.如果收到1个ARP回答,那末此时ARP结点是完全的,因此就知道了对方的硬件地址,该地址寄存sockaddr_dl结构中,
所有发往该地址的数据被将被发送。
3.如果其他主机发送1个ARP要求或回答,其中发送方的IP地址与本机相同,那末肯定有1个主机配置有误,Net/3将检测
到该过失,并向管理员等级1个报文。
4.如果主机收到来自其他主机的要求或回答,对应的ARP结点早已存在,但硬件地址发送了变化,那末ARP结点将被更新。
5.主机可以被配置成代理ARPhttp://www.wfuyu.com/server/,这类情况下,主机可以代其他主机响应ARP要求,在回答中提供其他主机的硬件地址。
代理ARP回答中对应目的硬件地址的主机必须能够把IP数据报发至ARP要求中指定的目的地址。
该函数的大概流程以下:
1.查找匹配的接口和IP地址。搜索本机的Internet地址链表(in_ifaddr结构的链表)。要记住1个接口可以有多个IP地址。
2.验证发送方的硬件地址。如果发送方的硬件地址等于本机接口的硬件地址。那是由于收到了本机发送的要求,疏忽该分组。
如果发送方的硬件地址等于以太网的广播地址,说明出错了。记录该过失,并抛弃该分组。
3.检查发送方IP地址。如果发送方IP地址等于本本机正在使用的1个IP地址,在本机系统配置出了过失。
4.在路由表中搜索与发送方IP地址匹配的结点。arplookup函数在ARP高速缓存中查找符合发送方的IP地址。当ARP分组中
目的地址就是本机,总是要穿件ARP结点的。
5.更新已有结点或填充新的结点。只有当以下3个条件为真时,语句才履行:
a.找到1个已有的ARP结点或成功创建1个新的ARP结点。
b.ARP结点指向1个路由表结点。
c.路由表结点的re_gateway字段指向1个sockaddr_dl结构。
6.检查发送方硬件地址是不是已改变。如果已改变,则记录发送方硬件地址,更新最近解析的ARP结点。
7.如果是该ARP操作不是要求,那末抛弃接收到的分组。
8.产生1个对应于ARP要求的回答。只有当以下两种情况时才会产生ARP回答:
a.本机就是该要求所要查找的目的主机。
b.本机是该要求所要查找的目的主机的ARP代理http://www.wfuyu.com/server/。
9.用以太网帧首部填充sockaddr。
10.将ARP回答传送至接口输出函数,并返回。
ARP结点1般是动态的,需要时创建,超时时自动删除。也允许管理员创建永久性结点。
arp_rtrequest函数使arptimer函数第1次被调用,随后arptimer每隔5分钟使自己被调用1次。arptimer查看ARP结点链表
中的每个结点,如果不是1个永久结点,而且时间已超时,那末arptfree就删除该结点。
ether_output函数调用arpresolve函数以取得对应某个IP地址的以太网地址。arpresolve函数利用llinfo_arp结构的la_hold
成员指针“保持”待发IP数据报,并发送1个ARP要求,收到ARP回答后,再将保持的IP数据报发送出去。
ARPresolve应避免ARP洪泛,也就是说,它不应在还没有收到ARP回答时高速重复发送ARP要求,出现这类情况主要有两个
缘由,第1,有多个IP数据报要发往同1个还没有解析硬件地址的主机;第2,1个IP数据报的每一个分片都会作为独立分组
调用ether_output。
Net/3采取以下方法来避免ARP泛洪。
1.Net/3不在同1秒内发送多个对应同1目的地的ARP要求。
2.如果在连续5个ARP要求(也就是5秒钟)后还没有收到回答,路由结点的RTF_REJECT标志置1,实现设为往后的20秒。
这会使ether_output在20秒内谢绝发往该目的地址的IP数据报。
3.20秒后,arpresolve会继续发送该目的主机的ARP要求。
arplookup函数调用选路函数rtalloc1在Internet路由表中查找ARP结点,我们已看到过3次调用arplookup的情况:
1.在in_arpinput中,在接收到ARP分组后,对应源IP地址查找或创建1个ARP结点。
2.在in_arpinput中,接收到ARP要求后,查看是不是存在目的硬件地址的代理ARP结点。
4.在arpresolve中,查找或创建1个对应待发送数据报IP地址的ARP结点。
如果arplookup履行成功,则返回1个指向对应llinfo_arp结构的指针,否则返回1个空指针。
下一篇 简析三层架构