udhcpd中调用各个模块完成dhcp服务器功能。
udhcpd执行首先是读入了DHCPD_CONF_FILE的配置文件,完成全局变量server_config的初始化工作。
之后将进程的pid加锁独占性地写入到文件中。再之后通过接口名,完成服务器接口索引MAC地址和IP地址的读取工作。
在调用daemon之后,再次写入dhcpd的pid。调用daemon之后将服务器进程设置为了守护进程在后台执行,但是其pid发生了变化,故此要再次写入。在文件中保存pid,是为了方便地查看到dhcp服务器守护进程的pid。
再之后创建了一个全双工管道,signal_pipe,并且设置了信号SIGUSR1和SIGTERM的捕捉函数signa_handler。之后进程阻塞select。等待管道数据的到来或是报文的到来。
这里服务器设计的函数比较巧妙的,试想一下,若客户端长时间不发送请求过来,而服务器这边我们想将内存中的租赁信息写入到文件中,那么该怎么办?服务器进程阻塞在select导致后续的操作不能够进行。
服务器这边使用的方法是,向进程发送信号,在信号捕捉函数里面向singalpipie管道无阻塞地写入信号,这样,服务器就不会阻塞于select了。同时后续代码也对接收到的数据进行了处理。
if (FD_ISSET(signal_pipe[0], &rfds)) {/*信号到达那么则进行处理*/ if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) continue; /* probably just EINTR */ switch (sig) { case SIGUSR1:/*收到SIGUSR1立即写租约*/ LOG(LOG_INFO, "Received a SIGUSR1"); write_leases(); /* why not just reset the timeout, eh */ timeout_end = time(0) + server_config.auto_time; continue; case SIGTERM:/*收到SIGTERM服务器立即退出*/ LOG(LOG_INFO, "Received a SIGTERM"); exit_server(0); } }
至于服务器后续的一些操作就是正常的状态机的转移操作了,并不难理解。
而客户端那边与服务器大致类似。
最后,说一下,本udhcp的实现版本,和rfc所描述的dhcp差距还是挺大的,它只是简简单单的实现了dhcp功能。很多功能,没有实现,这其中大致有如下几点:
1)只提供了IP地址的动态分配,不支持自动分配和手动分配;
2)服务器在为客户端找到可用IP后,并不使用PING探测该IP的可用性,而是直接使用ARP进行探测,这样当客户端获得服务器分配的IP地址后,就直接使用了,并不再次广播ARP报文;
3)当目前该版本并没有实现对于选项过载的支持,但可以通过扩展实现对其的支持;
不提供DHCP安全功能,DHCP Snooping功能等;
4)客户机永远不会主动释放IP;
5)客户机重启后,直接再次发送DHCPOFFER而不是DHCPREQUEST。
若要实现其他一些它原本就不存在的功能,就的自己进行扩展。在弄懂代码和熟知RFC2131和2132的情况下,扩展其实还是不难的。
更过信息请参见;
dhcp协议有限状态机
RFC2131:
http://www.ietf.org/rfc/rfc2131.txt
本人享有博客文章的版权,转载请标明出处http://blog.csdn.net/baidu20008