Chinaunix首页 | 论坛 | 博客
  • 博客访问: 316997
  • 博文数量: 90
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 113
  • 用 户 组: 普通用户
  • 注册时间: 2016-01-27 19:56
文章分类

全部博文(90)

文章存档

2017年(12)

2016年(78)

分类: LINUX

2016-11-21 15:17:06

原文地址:dhcpd 源码分析 作者:xlzxlz2

转:http://blog.csdn.net/lenovo_/article/details/6632307

dhcpd是linux下的一个DHCP服务器,下载地址:

下载完成后
tar -zxvf dhcp-4.2.1-P1.tar.gz
./configure
make
make install

编辑 /etc/dhcpd.conf 文件
ddns-update-style none;
subnet 192.168.66.0 netmask 255.255.255.0 {
  option routers 192.168.66.1;
  option subnet-mask 255.255.255.0;
  option domain-name "wayos";
  option domain-name-servers 61.139.2.69;
  range 192.168.66.2 192.168.66.254;
  default-lease-time 600;
  max-lease-time 7200;
}

192.168.66.0 为主机所在网段
如果程序提示没有 "/var/db/dhcpd.leases" 文件,touch 一个

main
{
/* Set up the isc and dns library managers */
/* Set up the client classification system. */
/* Initialize the omapi system. */
/* Set up the OMAPI wrappers for common objects. */
/* Set up the OMAPI wrappers for various server database internal
    objects. */
/* Initially, log errors to stderr as well as to syslogd. */
/* 解析命令行参数 */
/* get user and group info if those options were given */
/* get around the ISC declaration of group */
/* Default to the DHCP/BOOTP port. */
/* Set up the initial dhcp option universe. */
/* Add the ddns update style enumeration prior to parsing. */
/* Set up various hooks. */
 dhcp_interface_setup_hook = dhcpd_interface_setup_hook;
 bootp_packet_handler = do_packet;
/* Set up the standard name service updater routine. */
/* Initialize icmp support... */
/* Read the dhcpd.conf file... */
/* Start up the database... */
/* Discover all the network interfaces and initialize them. */
/* First part of becoming a daemon... */
/* Become session leader and get pid... */
/* Receive packets and dispatch them... */
dispatch ();
}

关键代码:

discover.c 文件中有bootp_packet_handler函数指针声明
void (*bootp_packet_handler) PROTO ((struct interface_info *,
         struct dhcp_packet *, unsigned,
         unsigned int,
         struct iaddr, struct hardware *));

dhcpd.c 文件中 main函数对bootp_packet_handler函数指针进行了赋值,然后调用discover_interfaces函数:
bootp_packet_handler = do_packet;
discover_interfaces(DISCOVER_SERVER);

discover.c 文件有discover_interfaces函数的定义,其中关键的调用了got_one函数:
status = omapi_register_io_object((omapi_object_t *)tmp,
         if_readsocket,
         0, got_one, 0, 0);

discover.c 文件有got_one函数定义,其关键代码是调用了receive_packet函数,和bootp_packet_handler函数指针:
receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)

 if (bootp_packet_handler) {
  ifrom.len = 4;
  memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len);

  (*bootp_packet_handler) (ip, &u.packet, (unsigned)result,
      from.sin_port, ifrom, &hfrom);
 }

socket.c 文件中有receive_packet函数的定义
result = recvfrom (interface -> rfdesc, (char *)buf, len, 0,
       (struct sockaddr *)from, &flen);

options.c 文件中有do_packet函数的定义:
packet_allocate (&decoded_packet, MDL);
decoded_packet -> raw = packet;
 decoded_packet -> packet_length = len;
 decoded_packet -> client_port = from_port;
 decoded_packet -> client_addr = from;
 interface_reference (&decoded_packet -> interface, interface, MDL);
 decoded_packet -> haddr = hfrom;
 /* If there's an option buffer, try to parse it. */
 if (decoded_packet -> packet_length >= DHCP_FIXED_NON_UDP + 4) {
  if (!parse_options (decoded_packet)) {
   if (decoded_packet -> options)
    option_state_dereference
     (&decoded_packet -> options, MDL);
   packet_dereference (&decoded_packet, MDL);
   return;
  }

  if (decoded_packet -> options_valid &&
      (op = lookup_option (&dhcp_universe,
      decoded_packet -> options,
      DHO_DHCP_MESSAGE_TYPE))) {
   struct data_string dp;
   memset (&dp, 0, sizeof dp);
   evaluate_option_cache (&dp, decoded_packet,
            (struct lease *)0,
            (struct client_state *)0,
            decoded_packet -> options,
            (struct option_state *)0,
            (struct binding_scope **)0,
            op, MDL);
   if (dp.len > 0)
    decoded_packet -> packet_type = dp.data [0];
   else
    decoded_packet -> packet_type = 0;
   data_string_forget (&dp, MDL);
  }
 }
  
 if (decoded_packet -> packet_type)
  dhcp (decoded_packet);
 else
  bootp (decoded_packet);

dhcp.c 文件有dhcp函数的定义,主要做的工作就是对不同的packet -> packet_type对应的包进行处理:
 switch (packet -> packet_type) {
       case DHCPDISCOVER:
  dhcpdiscover (packet, ms_nulltp);
  break;

       case DHCPREQUEST:
  dhcprequest (packet, ms_nulltp, lease);
  break;

       case DHCPRELEASE:
  dhcprelease (packet, ms_nulltp);
  break;

       case DHCPDECLINE:
  dhcpdecline (packet, ms_nulltp);
  break;

       case DHCPINFORM:
  dhcpinform (packet, ms_nulltp);
  break;

       case DHCPLEASEQUERY:
  dhcpleasequery(packet, ms_nulltp);
  break;

       case DHCPACK:
       case DHCPOFFER:
       case DHCPNAK:
       case DHCPLEASEUNASSIGNED:
       case DHCPLEASEUNKNOWN:
       case DHCPLEASEACTIVE:
  break;

       default:
  errmsg = "unknown packet type";
  goto bad_packet;
 }

dhcp.c 文件有dhcprequest函数的定义,此函数的执行流程为:
/* Find the lease that matches the address requested by the
    client. */
/*If it's RENEWING, we are the only server to hear it, so
   * we have to serve it.*/
/* If we do know where it came from and it asked for an
     address that is not on that shared network, nak it. */
/* If the address the client asked for is ours, but it wasn't
    available for the client, NAK it. */
/* Otherwise, send the lease to the client if we found one. */

阅读(1503) | 评论(0) | 转发(0) |
0

上一篇:DHCP的若干原理解释

下一篇:uboot编译全程

给主人留下些什么吧!~~