Server端对于租赁出去的IP的管理是基于结构体dhcpOfferedAddr的,该结构体的定义是在leases.c文件里:(结构体的成员介绍说明见详解之数据结构)

   1:  struct dhcpOfferedAddr {
   2:      uint8_t chaddr[16];
   3:      uint32_t yiaddr;    /* network order */
   4:      uint32_t expires;    /* host order */
   5:  };

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

在dhcpd.c文件里用该结构体定义指向该结构数组的指针leases;

/* dhcpd.c */

#include <leases.h>

struct dhcpOfferedAddr *leases;

在读取完配置信息server_config后,就可以依据配置信息的内存为该结构数组申请内存空间了:

   1:      /* 
   2:       * strut dhcpOfferedAddr {
   3:       *    uint8_t        chaddr[16];
   4:       *    uint32_t    yiaddr;            //network order
   5:       *    uint32_t    expires;        //host order
   6:       * };
   7:       *
   8:       * 该结构数组leases是记录租赁出去的IP,    yiaddr
   9:       * 租赁IP客户机的MAC, charddr
  10:       * 租赁的到期时间,expires(从1970年1月1日00:00:00到租赁到期的总共的秒数)
  11:       *
  12:       * dhcp server启动后(可能是异常重启)
  13:       * 所以要充server_config.file里读取上次为哪些客户机分配了IP
  14:       * 并把读取到的内容添加到leases数组里
  15:       */
  16:      leases = xzalloc(server_config.max_leases * sizeof(struct dhcpOfferedAddr));
  17:      read_leases(server_config.lease_file); 
  18:          //server_config.lease_file = "/var/lib/misc/udhcpd.leases"
  19:   

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

2). 查找租赁最早到期的租约:

   1:  /* 
   2:   * add a lease into the table, clearing out any old ones
   3:   * add_lease是把MAC:chaddr, IP : yiaddr, expires: lease
   4:   * 租赁信息添加到leases数组里
   5:   * 函数首先调用clear_lease把数组里旧的删除掉(与chaddr or yiaddr相同的)
   6:   * 从leases数组里找到最早到期的,再添加
   7:   *
   8:   * 返回oldest (NULL 表示未添加成功) 
   9:   */
  10:  struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease)
  11:  {
  12:      struct dhcpOfferedAddr *oldest;
  13:   
  14:      /* clean out any old ones */
  15:      clear_lease(chaddr, yiaddr);
  16:   
  17:      /* 从leases数组里找到一个最早到期的oldest,以便添加新的 */
  18:      oldest = oldest_expired_lease();
  19:   
  20:      if (oldest) //oldest != NULL ,Found...
  21:      {
  22:          memcpy(oldest->chaddr, chaddr, 16);
  23:          oldest->yiaddr = yiaddr;
  24:   
  25:          /* 
  26:           * 函数的第三个参数,即lease,表示的是租赁的剩余时间
  27:           * 在动态租赁数组leases里记录的租赁到期时间
  28:           *
  29:           * 所以 oldest->expires = time(0) + lease;
  30:           */
  31:          oldest->expires = time(0) + lease;
  32:      }
  33:   
  34:      return oldest;
  35:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

3). 通过MAC或IP查找租约:

   1:  /* Find the first lease that matches chaddr, NULL if no match */
   2:  struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr)
   3:  {
   4:      unsigned int i;
   5:   
   6:      for (i = 0; i < server_config.max_leases; i++)
   7:          if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]);
   8:   
   9:      return NULL;
  10:  }
  11:   
  12:  /* Find the first lease that matches yiaddr, NULL is no match */
  13:  struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)
  14:  {
  15:      unsigned int i;
  16:   
  17:      for (i = 0; i < server_config.max_leases; i++)
  18:          if (leases[i].yiaddr == yiaddr) return &(leases[i]);
  19:   
  20:      return NULL;
  21:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

4). 检查IP addr是否被网络中主机所使用,若被使用的话添加到leases数组里:

   1:  /*
   2:   * check is an IP is taken, if it is, add it to the lease table
   3:   *
   4:   * 检查addr is a free IP(网络中是否有主机使用addr)
   5:   * if addr is a used IP, 把addr添加到租赁数组里
   6:   *
   7:   *    1. 返回0 表示addr 是a free IP
   8:   *     2. 返回1表示addr已被网络中的某台主机使用了
   9:   *        并且把使用addr的主机添加到leases数组里
  10:   *        其中MAC: blank_chaddr, IP: addr, expires: server_config.confict_time(def: 3600sec)
  11:   *
  12:   */
  13:  static int check_ip(uint32_t addr)
  14:  {
  15:      struct in_addr temp;
  16:   
  17:      /* arpping()返回0表示addr used */
  18:      if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) {
  19:          temp.s_addr = addr;
  20:          LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds",
  21:              inet_ntoa(temp), server_config.conflict_time);
  22:   
  23:          /*
  24:           * 因为刚在未在leases数组里找到这个已被used 的IP
  25:           * 所以要把这个used IP添加到leases数组里
  26:           * 租赁客户机MAC 为blank_chaddr(黑户)
  27:           * 租赁的IP即used IP(addr)
  28:           * 租赁时间:server_config.conflict_time
  29:           */
  30:          add_lease(blank_chaddr, addr, server_config.conflict_time);
  31:          return 1;
  32:      } else return 0;
  33:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

5) 从可用IP地址池里找到一个可用的IP(a Free IP)

uint32_t find_address(int check_expire);

该函数的调用是在,server端接收到DHCPDISOCVER的报文的时候,会为client提供一个IP地址:

a) server首先利用client的MAC地址在leases数组里查找该client以前是否在这里租赁过IP,租赁过的话,把以前的IP提供给client

b) 第一种情况不满足的话,server会检查DHCPDISCOVER报文的选项字段,client是否有请求的IP(该选项信息的CODE :DHCP_REQUESTED_IP),有的话检查该IP是否为Free,可以的话把Request IP提供给client。

c) 上面两种情况都不满足的话,就调用find_address这个函数了。

   1:  /*
   2:   * find an assignable address, it check_expired is true,
   3:   * we check all the expired leases as well.
   4:   * Maybe this should try expired leases by age...
   5:   *
   6:   * 找到一个可分配的IP,如果check_expired is true,
   7:   * 会检查所有到期租约
   8:   * find_address()函数找到free IP 返回IP的值(network order)
   9:   * 未找到返回0
  10:   * 
  11:   */
  12:  uint32_t find_address(int check_expired)
  13:  {
  14:      uint32_t addr, ret;
  15:      struct dhcpOfferedAddr *lease = NULL;
  16:   
  17:      /*
  18:       * 在端上进行计算比较的时候使用 host order
  19:       * 一般存储的时候采用 network order
  20:       *
  21:       * 遍历整个可分配地址server_config.start -- server_config.end
  22:       */
  23:           /* addr is in host order here */
  24:      addr = ntohl(server_config.start);
  25:      for (;addr <= ntohl(server_config.end); addr++) 
  26:      {
  27:          /* ie, 192.168.55.0 */
  28:          if (!(addr & 0xFF)) continue;
  29:   
  30:          /* ie, 192.168.55.255 */
  31:          if ((addr & 0xFF) == 0xFF) continue;
  32:   
  33:          /* 
  34:           * Only do if it isn't 
  35:                   * an assigned as a static lease
  36:           * rexervedIP()检查addr是否在静态租赁链表里
  37:           * addr在静态链表的话,函数返回1,反之返回0
  38:           */
  39:          if(!reservedIp(server_config.static_leases, htonl(addr)))
  40:          {
  41:              /* lease is not taken */
  42:              ret = htonl(addr);
  43:   
  44:              /* !(lease = find_lease_by_yiaddr(ret)) 地址addr是否已被租赁出去了 */
  45:              if ((!(lease = find_lease_by_yiaddr(ret)) ||
  46:   
  47:                       /* 
  48:                        * or it expired and we are checking for expired leases
  49:                   * or 租赁出去的话,
  50:                   * addr是否是a free IP还取决与
  51:                   * lease_expired(lease)是否已到期和check_expired
  52:                   * 
  53:                        */
  54:                       (check_expired  && lease_expired(lease))) &&
  55:   
  56:                       /* 
  57:                        * and it isn't on the network
  58:                        * 如果addr满足上面两个条件的其中一个
  59:                        * 1.!(lease = find_lease_by_yiaddr(ret)) 没有被租赁出去                      * 2.(check_expired && lease_expired(lease)) 已被租赁出去了,
  60:                        * 但租赁过期了(check_expired == ture)
  61:                        *
  62:                        * addr 满足上面条件之一,还要检查addr是否被网络上其他主机使用
  63:                        * 
  64:                        * check_ip() 发送arp Request包确认addr是否被使用
  65:                        * 返回0, addr is a free IP
  66:                        */
  67:                       !check_ip(ret)) 
  68:              {
  69:              return ret;
  70:              break;
  71:              }
  72:          }
  73:      }
  74:      return 0;
  75:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

udhcp源码详解(四) 之租赁IP的管理的更多相关文章

  1. udhcp源码详解(五) 之DHCP包--options字段

    中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就可以大致的讲完,但实现的源码却要关心很多的问题,比如说 ...

  2. udhcp源码详解(二)--转

    定义的数据结构对于C程序的重要性,不言而喻.面向对象设计的程序是一个个对象的集合,而面向过程语言设计的程序则是数据结构与算法的集合. 下面来分析的是dhcp server中的定义结构体: 1).在pa ...

  3. udhcp源码详解(三)上 之配置信息的读取

    上节介绍了存储管理配置信息的结构体struct server_config_t,该结构体贯穿整个server端程序的运行. 在dhcpd.c里的用该结构体定义个一个全局的变量: struct serv ...

  4. udhcp源码详解(三) 下 之配置信息的读取

    上节讲解了read_config函数,读取配置信息到server_config的相应成员变量里,但read_config函数只负责把配置信息重文件里读出来,具体怎么把信息填写到指定的地址内,是调用ke ...

  5. udhcp源码详解(一)之文件组织结构(dhcp server) --转

    udhcp目录下有十几个源文件,一个源文件相对应一个模块,完成一系列相关的功能,例如在static_leases.c主要针对static_lease链表增删查找等操作. dhcpd.c——   整个d ...

  6. Mybatis源码详解系列(四)--你不知道的Mybatis用法和细节

    简介 这是 Mybatis 系列博客的第四篇,我本来打算详细讲解 mybatis 的配置.映射器.动态 sql 等,但Mybatis官方中文文档对这部分内容的介绍已经足够详细了,有需要的可以直接参考. ...

  7. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  8. [转]Linux内核源码详解--iostat

    Linux内核源码详解——命令篇之iostat 转自:http://www.cnblogs.com/york-hust/p/4846497.html 本文主要分析了Linux的iostat命令的源码, ...

  9. Shiro 登录认证源码详解

    Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...

随机推荐

  1. Java多线程的同步方式和锁机制

    Object.wait(miliSec)/notify()/notifyAll() 线程调用wait()之后可以由notify()唤醒,如果指定了miliSec的话也可超时后自动唤醒.wait方法的调 ...

  2. cobbler 无人值守-介绍

    cobbler 介绍 快速网络安装linux操作系统的服务,支持众多的Linux版本,也支持网络安装windows系统 PXE的二次封装,将多种安装参数封装到一个菜单 它是由Python编写的 还可以 ...

  3. Linux 命令学习(1): head和tail

    版权声明:本文为博主原创文章,未经允许,不得转载. head head 命令可以将一段文本的开头一部分输出到标准输出. head命令既可以处理文本文件也可以处理标准输入. 基本应用 处理文本文件: h ...

  4. vue App.vue router 过渡效果, keep-alive 结合使用示例

    1, router.js配置 每个路由的index值 2, router.js配置 每个路由的keepAlive值 app.vue 代码 <template> <div id=&qu ...

  5. php 后端规范

    后端框架地址: git@gitee.com:xielisen/xcore.git 框架使用规范,内部沟通 Controller命名规范 1, 首字母大写,其余小写 2, 对应数据库名称. 不要下划线 ...

  6. LeetCode(169)Majority Element

    题目 Given an array of size n, find the majority element. The majority element is the element that app ...

  7. SQLServer__问题记录

    “备份集中的数据库备份与现有的xx数据库不同”  参考链接: http://www.cnblogs.com/huangfr/archive/2012/08/09/2629687.html RESTOR ...

  8. 跟初学者学习IbatisNet第一篇

    写在前面的话:我自己也是一个初学者,写这个专题只是为了对学过知识的巩固,如果有什么不对的地方,欢迎大家指正…………………… 第一篇就简单介绍一下什么是IbatisNet,然后写一个简单的Demo,在后 ...

  9. hdu 4460spfa用map来实现

    #include<stdio.h> #include<string.h>   #include <iostream> #include <algorithm& ...

  10. [NOIP1999] 提高组 洛谷P1014 Cantor表

    题目描述 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的.他是用下面这一张表来证明这一命题的: 1/1 1/2 1/3 1/4 1/5 … 2/1 2/2 2/3 2/4 … ...