您的位置:首页 > 理论基础 > 计算机网络

深入理解iputils网络工具-第8篇 rdisk:路由表更新程序

2012-12-28 11:18 253 查看

8.1 引言

初始化路由表有很多种方法,其中使用ICMP路由器发现报文就是一种方法。rdisc程序正是使用ICMP路由器发现报文来完成路由表的初始化和更新。

rdisc程序根据编译的不同可以程序可以编译成具有或没有服务器功能。如果设置了RDISC_SERVER宏,则会有服务器的功能,也就是会对ICMP报文路由器请求报文进行回复。否则,不会对ICMP报文路由器请求报文进行回复。

ICMP路由器发现报文格式可以参看RFC 1256。

8.2 rdisc程序的使用

ICMP路由发现报文目前使用的并不多,对rdisc的测试也并不方便。

rdisc程序的选项的解释如下:

-a

将所有路由加入内核路由项,不管优先级是多大。

-b

与-a选项相反,在接受ICMP路由通告报文时,只将优先级最高的路由加入内核路由项,而删除那些低优先级的路由。

-d

设置为debug模式。

-f

即使没有发现任何路由也永远运行程序。一般情况下,如果程序在发送3个请求报文之后仍然没有接受到通告报文就退出运行,并返回非零值。

注意:-f参数能够覆盖-s参数的效果。

-p <preference>

在发送ICMP路由器通告报文是,需要在对应路由器地址字段后面设置4字节的优先级字段。这个字段就是本地接口地址的优先级。

在初始化的时候,会将所有存储的本机接口的优先级设置为<preference>。

-s

程序快速发送3个请求报文,以快速找出路由。如果此后没有接收到报文就退出运行,并返回非零值。

注意:-f参数能够覆盖-s参数的效果。

-t

测试模式。

设置这个选项使得程序不退居后台运行。

-T <interval>

将在网络接口发送ICMP路由器通告报文的最大的时间间隔设置为<interval>。单位是秒。

注意:RFC 1256协议里规定此时间间隔不得小于4秒,不得超过1800妙,默认值是MAX_ADV_INT(600)。

-v

冗余输出模式,也就是向log中输出很多debug信息。

-V

打印出版本信息,然后退出。

8.3 rdisc程序的流程图

这里画出的流程图是具有服务器功能的程序的流程图,如下所示:











8.4 rdisc.c程序的全局变量的分析

static int num_interfaces;

本地主机网络接口总数。

static struct interface *interfaces;

本地主机的所有接口数据。

在初始化的时候,需要通过ioctl()函数取得所有本机借口的信息,存储在interfaces数组中。

在进行ICMP路由通告时,需要对所有的接口对应地址进行广播、多播或者单播。

static int interfaces_size; /* Number of elements in interfaces */

interfaces数组的个数,也就是符合条件的网络接口的个数。

#define MAXPACKET 4096

ICMP报文的最大字节数。

在分配给ICMP报文存储空间的时候使用。

int debugfile;



程序中没有使用到这个变量。

char usage[];

存储了的程序的用法介绍。

int s;

ICMP报文的socket文件。

struct sockaddr_in whereto;

发送ICMP报文的目的地址信息。

如果本地主机支持多播则向224.0.0.2(all-routers IP multicast group)发送数据,否则向255.255.255.255发送ICMP路由报文。

目的地址还可以自行设置。

int verbose = 0;

标识是不是打印冗余信息。

如果设置为1,则会打印文件出很多信息。

可以通过-v设置。

int debug = 0;

标识是不是debug模式。

如果设置为1,则会打印文件打印很多debug信息。

可以通过-d设置。

int trace = 0;

标识是不是不在后台运行。

如果设置为1,则在程序运行之后,不会退到后台运行,也不会关闭标准输入输出,错误消息也打印在标准输出上,可以方便调试。

可以通过-t设置。

int solicit = 0;

可以通过-s设置。

int ntransmitted = 0;

发送的ICMP路由报文总数。

在发送一个ICMP路由报文之后加1,在退出程序的时候作为统计数据打印出来。

int nreceived = 0;

接收到的ICMO路由报文总数。

在接收一个ICMP路由报文之后加1,在退出程序的时候作为统计数据打印出来。

int forever = 0;

可以通过-f选项设置为1。

#ifdef RDISC_SERVER

由于编译选项的不同,程序可以编译成具有或没有服务器功能。如果设置了RDISC_SERVER宏,则会有服务器的功能,也就是会对ICMP报文路由器请求报文进行回复。

int responder;

标识是否对ICMP路由请求报文进行回复。

设置为0则不回复。

可以通过-r设置为1。

int max_adv_int = MAX_ADV_INT;

在网络接口发送ICMP路由器通告报文的最大的时间间隔。单位是秒。

RFC 1256协议里规定max_adv_int不得小于4秒,不得超过1800妙。默认值是MAX_ADV_INT(600)。

可以通过-T选项设置,设置后会相应改变min_adv_int、lifetime的值。

int min_adv_int;

在网络接口发送ICMP路由器通告报文的最小的时间间隔。单位是秒。

RFC 1256协议里规定min_adv_int不得小于3秒,不得超过max_adv_int。其默认值是0.75 * max_adv_int。

在实际中,在网络接口发送ICMP路由器通告报文的最大的时间间隔是一个随机数,但是保证了时间间隔不小于min_adv_int,不大于max_adv_int。计算式子如下:

min_adv_int+ ((max_adv_int - min_adv_int) *(random() % 1000)/1000);

int lifetime;

放置在ICMP路由器报告报文中的生存时间字段的值。单位是秒。

RFC 1256协议里规定不得小于max_adv_int,不得大于9000秒,默认值是3 *max_adv_int。

int initial_advert_interval =MAX_INITIAL_ADVERT_INTERVAL;

在网络接口刚刚开始传输ICMP路由器通告报文的时候,需要定期传输公告报文,间隔间隔为MAX_INITIAL_ADVERT_INTERVAL秒。

FC 1256协议里规定MAX_INITIAL_ADVERT_INTERVAL为16,传输次数MAX_INITIAL_ADVERTISEMENTS为3。

int initial_advertisements = MAX_INITIAL_ADVERTISEMENTS;

在网络接口刚刚开始传输ICMP路由器通告报文的时候,需要定期传输公告报文,间隔间隔为MAX_INITIAL_ADVERT_INTERVAL秒。

FC 1256协议里规定MAX_INITIAL_ADVERT_INTERVAL为16,传输次数MAX_INITIAL_ADVERTISEMENTS为3。

int preference = 0;

在发送ICMP路由器通告报文是,需要在对应路由器地址字段后面设置4字节的优先级字段。这个字段就是本地接口地址的优先级。

在初始化的时候,会将所有interfaces中存储的本机接口的优先级设置为preference。

可以通过-p选项设置。

#endif

int max_solicitations = MAX_SOLICITATIONS;

在程序接口初始的情况下,允许网络接口连续发送MAX_SOLICITATIONS个ICMP路由器请求报文,发送时间间隔为SOLICITATION_INTERVAL。

FC 1256协议里规定时间间隔SOLICITATION_INTERVAL为3秒, 传输次数MAX_SOLICITATIONS为3个。

unsigned int solicitation_interval =SOLICITATION_INTERVAL;

在程序接口初始的情况下,允许网络接口连续发送MAX_SOLICITATIONS个ICMP路由器请求报文,发送时间间隔为SOLICITATION_INTERVAL。

FC 1256协议里规定时间间隔SOLICITATION_INTERVAL为3秒, 传输次数MAX_SOLICITATIONS为3个。发送时间间隔没有随机性。

int best_preference = 1;

标识内核中使用的路由项是不是只使用优先级最高的路由。

如果设置为1,则在接受ICMP路由通告报文时,只将优先级最高的路由加入内核路由项,而删除那些低优先级的路由。

可以通过-a选项设置为0。

可以通过-b选项设置为1。

static int logging = 0;

标识是不是使用文件来记录log信息。

如果使用了-t选项,则程序不会退居后台运行,则logging维持0,仍然将输出打印在标准输出上。

如果没有使用-t选项,则程序退居后台运行,则logging变为1,将输出打印在in.rdiscd的文件里。

char *sendaddress;

发送ICMP报文的目的地址。

如果本地主机支持多播则向224.0.0.2(all-routers IP multicast group)发送数据,否则向255.255.255.255发送ICMP路由报文

目的地址还可以自行设置。

char *recvaddress;

接收ICMP报文的目的地址。

如果本地主机支持多播则向224.0.0.1(all-systems IP multicast group)发送数据,否则向255.255.255.255发送ICMP路由报文

目的地址还可以自行设置。

struct table {

structin_addr router;

int preference;

int remaining_time;

int in_kernel;

struct table *next;

} *table;

存储路由的列表项。

当接受到ICMP路由器通告报文时,将所有的路由器地址及其优先级存储在table列表中。并根据best_preference的设置,将table列表中部分路由项加入内核中使用。

8.5 ICMP路由发现报文格式

ICMP路由器请求报文格式如下所示:



ICMP路由器通告报文格式如下所示:



8.6 ioctl系统调用

ioctl系统调用提供一个通用命令接口,程序可以用它来访问一个设备的标准系统调用所不支持的特性。

rdisc.c使用了很多的ioctl系统调用函数,其中在iputils中使用过的ioctl选项的解释如下:

类别

请求

描述

套接口

SIOCGIFNUM

找到网络接口的个数

SIOCGSTAMP

取得时间戳

文件

FIONBIO

设置/清除非阻塞标志

套接口配置控制

SIOCGIFCONF

获取所有接口的列表

SIOCGIFFLAGS

取得接口标识

SIOCGIFINDEX

由接口名字获得接口标号(index)

SIOCGIFDSTADDR

获取点到点地址

SIOCGIFNETMASK

获取子网掩码

SIOCGIFHWADDR

取得网络设备的硬件地址

SIOCGIFNAME

获取接口的名字

SIOCGIFBRDADDR

获取广播地址

ARP

SIOCSARP

创建修改ARP项

路由表

SIOCADDRT

增加路径

SIOCDELRT

删除路径

终端I/O

TIOCGWINSZ

取得窗口大小

另外在rarpd.c、 tftpd.c、ping_common.c、ping.c、arping.c都使用了ioctl函数。

套接口操作相关的ioctl参数可以参看/linux-2.6.27/include/linux/sockios.h。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: