zoukankan      html  css  js  c++  java
  • udhcp源码详解(四) 之租赁IP的管理

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

    [cpp] view plaincopy

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

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

    /* dhcpd.c */

    #include <leases.h>

    struct dhcpOfferedAddr *leases;

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

    [cpp] view plaincopy

    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"

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

    [cpp] view plaincopy

    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. struct dhcpOfferedAddr *oldest; 
    12. /* clean out any old ones */
    13.     clear_lease(chaddr, yiaddr); 
    14. /* 从leases数组里找到一个最早到期的oldest,以便添加新的 */
    15.     oldest = oldest_expired_lease(); 
    16. if (oldest) //oldest != NULL ,Found...
    17.     { 
    18.         memcpy(oldest->chaddr, chaddr, 16); 
    19.         oldest->yiaddr = yiaddr; 
    20. /*
    21.          * 函数的第三个参数,即lease,表示的是租赁的剩余时间
    22.          * 在动态租赁数组leases里记录的租赁到期时间
    23.          *
    24.          * 所以 oldest->expires = time(0) + lease;
    25.          */
    26.         oldest->expires = time(0) + lease; 
    27.     } 
    28. return oldest; 

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

    [cpp] view plaincopy

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

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

    [cpp] view plaincopy

    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. struct in_addr temp; 
    15. /* arpping()返回0表示addr used */
    16. if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) { 
    17.         temp.s_addr = addr; 
    18.         LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds", 
    19.             inet_ntoa(temp), server_config.conflict_time); 
    20. /*
    21.          * 因为刚在未在leases数组里找到这个已被used 的IP
    22.          * 所以要把这个used IP添加到leases数组里
    23.          * 租赁客户机MAC 为blank_chaddr(黑户)
    24.          * 租赁的IP即used IP(addr)
    25.          * 租赁时间:server_config.conflict_time
    26.          */
    27.         add_lease(blank_chaddr, addr, server_config.conflict_time); 
    28. return 1; 
    29.     } else return 0; 

    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这个函数了。

    [cpp] view plaincopy

    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.     uint32_t addr, ret; 
    14. struct dhcpOfferedAddr *lease = NULL; 
    15. /*
    16.      * 在端上进行计算比较的时候使用 host order
    17.      * 一般存储的时候采用 network order
    18.      *
    19.      * 遍历整个可分配地址server_config.start -- server_config.end
    20.      */
    21. /* addr is in host order here */
    22.     addr = ntohl(server_config.start); 
    23. for (;addr <= ntohl(server_config.end); addr++)  
    24.     { 
    25. /* ie, 192.168.55.0 */
    26. if (!(addr & 0xFF)) continue; 
    27. /* ie, 192.168.55.255 */
    28. if ((addr & 0xFF) == 0xFF) continue; 
    29. /*
    30.          * Only do if it isn't
    31.                  * an assigned as a static lease
    32.          * rexervedIP()检查addr是否在静态租赁链表里
    33.          * addr在静态链表的话,函数返回1,反之返回0
    34.          */
    35. if(!reservedIp(server_config.static_leases, htonl(addr))) 
    36.         { 
    37. /* lease is not taken */
    38.             ret = htonl(addr); 
    39. /* !(lease = find_lease_by_yiaddr(ret)) 地址addr是否已被租赁出去了 */
    40. if ((!(lease = find_lease_by_yiaddr(ret)) || 
    41. /*
    42.                      * or it expired and we are checking for expired leases
    43.                  * or 租赁出去的话,
    44.                  * addr是否是a free IP还取决与
    45.                  * lease_expired(lease)是否已到期和check_expired
    46.                  *
    47.                      */
    48.                     (check_expired  && lease_expired(lease))) && 
    49. /*
    50.                      * and it isn't on the network
    51.                      * 如果addr满足上面两个条件的其中一个
    52.                      * 1.!(lease = find_lease_by_yiaddr(ret)) 没有被租赁出去                    * 2.(check_expired && lease_expired(lease)) 已被租赁出去了,
    53.                      * 但租赁过期了(check_expired == ture)
    54.                      *
    55.                      * addr 满足上面条件之一,还要检查addr是否被网络上其他主机使用
    56.                      *
    57.                      * check_ip() 发送arp Request包确认addr是否被使用
    58.                      * 返回0, addr is a free IP
    59.                      */
    60.                     !check_ip(ret))  
    61.             { 
    62. return ret; 
    63. break; 
    64.             } 
    65.         } 
    66.     } 
    67. return 0; 
  • 相关阅读:
    Code Forces Gym 100886J Sockets(二分)
    CSU 1092 Barricade
    CodeChef Mahesh and his lost array
    CodeChef Gcd Queries
    CodeChef GCD2
    CodeChef Sereja and LCM(矩阵快速幂)
    CodeChef Sereja and GCD
    CodeChef Little Elephant and Balance
    CodeChef Count Substrings
    hdu 4001 To Miss Our Children Time( sort + DP )
  • 原文地址:https://www.cnblogs.com/woainilsr/p/3181028.html
Copyright © 2011-2022 走看看