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. WEB 前端模块化,读文笔记

    文章链接 WEB 前端模块化都有什么? 知识点 根据平台划分 浏览器 AMD.CMD 存在网络瓶颈,使用异步加载 非浏览器 CommonJS 直接操作 IO,同步加载 浏览器 AMD 依赖前置 req ...

  2. [POJ] 2223 Muddy Fields

    Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11490 Accepted: 4270 Description Rain has ...

  3. ubuntu中执行docker info出现警告信息WARNING: No memory limit support 或 WARNING: No swap limit support

    docker info 指令报若下错误:WARNING: No memory limit support 或WARNING: No swap limit support 解决方法: 1.打开/etc/ ...

  4. Linux离线安装redis集群

    一.应用场景介绍 本文主要是介绍Redis集群在Linux环境下的安装讲解,联网环境安装较为简单,这里只说脱机的Linux环境下是如何安装的.因为大多数时候,公司的生产环境是在内网环境下,无外网,服务 ...

  5. c++_核桃的数量

    #include <iostream> using namespace std; int gcd(int x,int y){ int temp; ){ temp=x%y; x=y; y=t ...

  6. rails使用bootstrap

    在Gemfile文件中添加'bootstrap-sass',再运行bundle install gem 'bootstrap-sass' 在config/application.rb添加一行代码,让b ...

  7. 【02】一个实现h5的拖放的整个过程-魔芋

    [02]拖放的整个过程-魔芋   01,创建2个元素,一个为拖放元素dragEle,一个是存放的元素targetEle.添加一些样式.   <div class="dragEle&qu ...

  8. Couchbase IV(管理与维护)

    Couchbase IV(管理与维护) 管理 常用命令 Command Description server-list List all servers in a cluster server-inf ...

  9. 查看linux ubuntu版本

    ubuntu版本: lsb_release -a  linux版本: uname -a proc目录下记录的当前系统运行的各种数据,version记录的版本信息直接可以通过cat查看到. 使用命令:c ...

  10. Fiddler抓包-get与post请求

    from:https://www.cnblogs.com/yoyoketang/p/6719717.html 本篇以博客园的请求为例,简单分析get与post数据有何不一样,以后也能分辨出哪些是get ...