生活随笔
收集整理的這篇文章主要介紹了
udhcp源码详解(四) 之租赁IP的管理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Server端對于租賃出去的IP的管理是基于結構體dhcpOfferedAddr的,該結構體的定義是在leases.c文件里:(結構體的成員介紹說明見詳解之數據結構)
[cpp] view plaincopy
struct dhcpOfferedAddr {? ??? uint8_t chaddr[16];? ??? uint32_t yiaddr;??? /* network order */??? uint32_t expires;?? /* host order */};? 在dhcpd.c文件里用該結構體定義指向該結構數組的指針leases;
/* dhcpd.c */
#include <leases.h>
struct dhcpOfferedAddr *leases;
在讀取完配置信息server_config后,就可以依據配置信息的內存為該結構數組申請內存空間了:
[cpp] view plaincopy
/* * strut dhcpOfferedAddr { *? uint8_t???? chaddr[16]; *? uint32_t??? yiaddr;???????? //network order *? uint32_t??? expires;??????? //host order * }; * * 該結構數組leases是記錄租賃出去的IP,?? yiaddr * 租賃IP客戶機的MAC, charddr * 租賃的到期時間,expires(從1970年1月1日00:00:00到租賃到期的總共的秒數) * * dhcp server啟動后(可能是異常重啟) * 所以要充server_config.file里讀取上次為哪些客戶機分配了IP * 并把讀取到的內容添加到leases數組里 */leases = xzalloc(server_config.max_leases * sizeof(struct dhcpOfferedAddr));? read_leases(server_config.lease_file);?? //server_config.lease_file = "/var/lib/misc/udhcpd.leases"2). 查找租賃最早到期的租約:
[cpp] view plaincopy
/* * add a lease into the table, clearing out any old ones * add_lease是把MAC:chaddr, IP : yiaddr, expires: lease * 租賃信息添加到leases數組里 * 函數首先調用clear_lease把數組里舊的刪除掉(與chaddr or yiaddr相同的) * 從leases數組里找到最早到期的,再添加 * * 返回oldest (NULL 表示未添加成功) */struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease)? {? struct dhcpOfferedAddr *oldest;? /* clean out any old ones */??? clear_lease(chaddr, yiaddr);? /* 從leases數組里找到一個最早到期的oldest,以便添加新的 */??? oldest = oldest_expired_lease();? if (oldest) //oldest != NULL ,Found...??? {? ??????? memcpy(oldest->chaddr, chaddr, 16);? ??????? oldest->yiaddr = yiaddr;? /* ???????? * 函數的第三個參數,即lease,表示的是租賃的剩余時間???????? * 在動態租賃數組leases里記錄的租賃到期時間???????? *???????? * 所以 oldest->expires = time(0) + lease;???????? */??????? oldest->expires = time(0) + lease;? ??? }? return oldest;? }? 3). 通過MAC或IP查找租約:
[cpp] view plaincopy
/* Find the first lease that matches chaddr, NULL if no match */struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr)? {? ??? unsigned int i;? for (i = 0; i < server_config.max_leases; i++)? if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]);? return NULL;? }? /* Find the first lease that matches yiaddr, NULL is no match */struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)? {? ??? unsigned int i;? for (i = 0; i < server_config.max_leases; i++)? if (leases[i].yiaddr == yiaddr) return &(leases[i]);? return NULL;? }? 4). 檢查IP addr是否被網絡中主機所使用,若被使用的話添加到leases數組里:
[cpp] view plaincopy
/* * check is an IP is taken, if it is, add it to the lease table * * 檢查addr is a free IP(網絡中是否有主機使用addr) * if addr is a used IP, 把addr添加到租賃數組里 * *? 1. 返回0 表示addr 是a free IP *? 2. 返回1表示addr已被網絡中的某臺主機使用了 *????? 并且把使用addr的主機添加到leases數組里 *????? 其中MAC: blank_chaddr, IP: addr, expires: server_config.confict_time(def: 3600sec) * */static int check_ip(uint32_t addr)? {? struct in_addr temp;? /* arpping()返回0表示addr used */if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) {? ??????? temp.s_addr = addr;? ??????? LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds",? ??????????? inet_ntoa(temp), server_config.conflict_time);? /*???????? * 因為剛在未在leases數組里找到這個已被used 的IP???????? * 所以要把這個used IP添加到leases數組里???????? * 租賃客戶機MAC 為blank_chaddr(黑戶)???????? * 租賃的IP即used IP(addr)???????? * 租賃時間:server_config.conflict_time???????? */??????? add_lease(blank_chaddr, addr, server_config.conflict_time);? return 1;? ??? } 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
/* * find an assignable address, it check_expired is true, * we check all the expired leases as well. * Maybe this should try expired leases by age... * * 找到一個可分配的IP,如果check_expired is true, * 會檢查所有到期租約 * find_address()函數找到free IP 返回IP的值(network order) * 未找到返回0 * */uint32_t find_address(int check_expired)? {? ??? uint32_t addr, ret;? struct dhcpOfferedAddr *lease = NULL;? /*???? * 在端上進行計算比較的時候使用 host order???? * 一般存儲的時候采用 network order???? *???? * 遍歷整個可分配地址server_config.start -- server_config.end???? *//* addr is in host order here */??? addr = ntohl(server_config.start);? for (;addr <= ntohl(server_config.end); addr++)?? ??? {? /* ie, 192.168.55.0 */if (!(addr & 0xFF)) continue;? /* ie, 192.168.55.255 */if ((addr & 0xFF) == 0xFF) continue;? /* ???????? * Only do if it isn't ???????????????? * an assigned as a static lease???????? * rexervedIP()檢查addr是否在靜態租賃鏈表里???????? * addr在靜態鏈表的話,函數返回1,反之返回0???????? */if(!reservedIp(server_config.static_leases, htonl(addr)))? ??????? {? /* lease is not taken */??????????? ret = htonl(addr);? /* !(lease = find_lease_by_yiaddr(ret)) 地址addr是否已被租賃出去了 */if ((!(lease = find_lease_by_yiaddr(ret)) ||? /* ???????????????????? * or it expired and we are checking for expired leases???????????????? * or 租賃出去的話,???????????????? * addr是否是a free IP還取決與???????????????? * lease_expired(lease)是否已到期和check_expired???????????????? * ???????????????????? */??????????????????? (check_expired? && lease_expired(lease))) &&? /* ???????????????????? * and it isn't on the network???????????????????? * 如果addr滿足上面兩個條件的其中一個???????????????????? * 1.!(lease = find_lease_by_yiaddr(ret)) 沒有被租賃出去??????????????????? * 2.(check_expired && lease_expired(lease)) 已被租賃出去了,???????????????????? * 但租賃過期了(check_expired == ture)???????????????????? *???????????????????? * addr 滿足上面條件之一,還要檢查addr是否被網絡上其他主機使用???????????????????? * ???????????????????? * check_ip() 發送arp Request包確認addr是否被使用???????????????????? * 返回0, addr is a free IP???????????????????? */??????????????????? !check_ip(ret))?? ??????????? {? return ret;? break;? ??????????? }? ??????? }? ??? }? return 0;? }?
轉載于:https://www.cnblogs.com/woainilsr/p/3181028.html
總結
以上是生活随笔為你收集整理的udhcp源码详解(四) 之租赁IP的管理的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。