dhcpd 源碼分析

來源:互聯網
上載者:User
 

dhcpd是linux下的一個DHCP伺服器,:
https://www.isc.org/software/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. */

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.