
在dhcpd.c里的用该结构体定义个一个全局的变量:
struct server_config_t server_config;
在server启动做的第一件事就是初始化这个全局变量server_config:

现在就进入read_config函数,一睹其真容!
学习这个函数,在以后遇到要读取配置信息可以参照read_config函数的写法。
read_config函数的定义是在file.c文件里。
分析read_config函数之前先来看一个结构体数组:
结构体的定义:

该结构体数组的定义以及初始化:

结构体名和数组名可以看出,config_keyword,配置信息关键字,正如其名,是辅助读取配置信息的。
数组里的每个config_keyword结构体元素中的keyword成员的值,与server_config_t里的成员变量名一一对应,该成员指示的就是配置的是server_config_t里的哪个成员。
读取配置信息的操作,配置信息读取存储到哪里,以及配置信息的默认值,这些由config_keywork里的后面的3个成员给出的。
成员heandler是一个函数指针,指向的函数即提供了怎么读取配置信息,以及把配置信息写到指定地址内。
arg, def则作为handler指向函数的两个各参数,arg告诉函数把配置信息存储到的地址,def则是配置信息的值,def是配置信息的默认值。
keyword数组里每个元素里的函数指针handler指向的这些函数,其定义都在file.c文件里。
handler函数的类型 : int (const *handler)(const char *line, void *arg)
1) read_ip: 把字符串格式的IP地址转换成uint32_t的IP格式,并存储到arg所指的内存。
2) read_u32: 把字符串格式的数转换成uint32_t类型数字,并存储到arg所指的内存。
3) read_yn: line字符串是“yes” 还是 “no”?若“yes”,将arg所指的内存赋1,反之,赋0
4) read_str:首先free(*arg)释放掉*arg指的内存,再根据字符串line的大小分配内存,并把line里的值复制到里面,让*arg指向新分配的内存。
5) read_opt: 从字符串line里读取options写到*arg所指的struct option_set链表里。(链表的每个结点data以CLV方式组织数据)。
read_opt对选项的信息的读取借助里也借助结构数组(在options.c里定义的),所以函数比较复杂,这里只用知道函数作用。
6) read_staticlease:从line字符串里读取MAC、IP地址字符串里MAC与IP用’/t’or’=’作为分隔)再把MAC和IP添加到*arg所指的static_lease链表里。static_lease链表是dhcp Server管理已租赁出去的IP和获得该IP的客户机的MAC绑定。
7) read_mac: 从字符串格式MAC地址里读出MAC并转化的MAC存储arg所指的内存里
上面的read_xxx函数,read成功返回1, 失败返回0。
上面讲解的这么的多都是read_config函数的基础,好啦,现在正式进入read_config函数:

若read_config函数到这就结束了,server依靠这些默认配置的值也可以工作(options字段没有默认值,不能给client其他的网络配置,但可以给client端分配IP的),但这样的话,程序就缺乏灵活性,IP地址池不能修改,租赁时间无法设定等。


上面这段就是从文件里读取配置信息,下面是摘自udhcp.conf文件的部分配置信息:

while(fgets(buffer, READ_CONFIG_BUF_SIZE, in))
每次从文件里读取一行,存放在buffer里,在对buffer处理,空行、注释行(还有只有token, 没有line的)直接跳过继续读取下一行。
token = strtok(buffer, “ /t”); 取到该行的keyword (文件里key与value之间使用空格或’/t’)
line = strtok(NULL, “”); 取到该行的配置信息值
这样(还需简单处理下)就可以根据keywords数组把从文件读取到的配置信息写到server_config相应的成员里。
差不多了,总结下read_config函数,她对配置的对象全局变量server_conifg,通过一个辅助结构数组来对server_config里的成员变量进行赋值的。真正对于成员的赋值操作都是通过数组里元素的函数指针handler指向的函数进行的。
read_config只是做了从文件的每行读出信息,并作些处理,得到token和line,利用token在数组里找到对应的handler和arg,………
read_config函数,读取配置信息到server_config的相应成员变量里,但read_config函数只负责把配置信息重文件里读出来,具体怎么把信息填写到指定的地址内,是调用keywords数组里元素的handler成员指向的函数完成。这节就是讲解完成具体的写入操作中比较复杂的函数。
1) int read_opt(const char *line, void *arg)
在read_config从udhcpd.conf里读到 token = “opt” 或 “option”;
摘自udhcp.conf里的options配置信息
调用handler: read_opt
const_line的从udhcpd.conf的读出的line
line的值 例:
dns 192.168.10.2 192.168.10.10
subnet 255.255.255.0 等
arg的值是 &(server_config.options)
即是把line的值存储到头结点为*arg的链表里去。
read_opt函数与read_config有点类似,也借助一个辅助的数组进行信息添加。
在以前章节有讲解过选项信息的存储组织方式,CLV:Code + Length + Value,value我们文件里读出来了,Code和Length在哪?
现在来看下这个辅助数组:
元素结构体的定义:

该结构体定义的数组:
这个辅助数组的做法与read_config里的有些类似,name即是keyword,flag可以求出Length,code即Code。
讲解这些函数真是痛苦,给你下套,而且是一环套一环的!
得到了每个选项信息里的value,其值保存在opt指向的内存,value长度为length,Code在struct dhcp_option类型的option里。
调用attach_option函数把选项信息的添加到server_config.options选项链表里。
/*
* add an option to the opt_list
*
* attach_option函数把从文件里读出的以options 或opt标识的配置信息
* 在函数read_opt,通过option->flag处理好了line里val 值 存放在buffer
* 再把配置信息填入到struct option_set的链表里
*
* 参数:opt_list: &(server_config.options)
* option: 根据选项头确定的dhcp_options数组里的一项
* buffer 配置信息(去除了option/opt和选项头,而且已经转换过了)
* length 配置信息的大小(以字节为单位)
*/
static void attach_option(struct option_set **opt_list, struct dhcp_option *option, char *buffer, int length);
添加到链表里分为两种情况
①链表里没有与将要添加的选项信息的Code一样的结点,直接添加到链表即可。
②链表里已有与将要添加的选项信息的Code一样的结点,该Code选项信息flag选项里OPT_LIST(例如:dns选项的value是IP List 有两个IP):
}
2)、int read_staticlease(const char *line, void *arg)
udhcpd.conf里static lease:


相关文章本文地址:https://blog.sxx1314.com/linux/134.html
版权声明:若无注明,本文皆为“unix 软硬件 技术宅 ”原创,转载请保留文章出处。百度已收录















