leases.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * leases.c -- tools to manage DHCP leases
  4. * Russ Dill <Russ.Dill@asu.edu> July 2001
  5. */
  6. #include "common.h"
  7. #include "dhcpd.h"
  8. uint8_t blank_chaddr[] = {[0 ... 15] = 0};
  9. /* clear every lease out that chaddr OR yiaddr matches and is nonzero */
  10. void clear_lease(uint8_t *chaddr, uint32_t yiaddr)
  11. {
  12. unsigned int i, j;
  13. for (j = 0; j < 16 && !chaddr[j]; j++);
  14. for (i = 0; i < server_config.max_leases; i++)
  15. if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) ||
  16. (yiaddr && leases[i].yiaddr == yiaddr)) {
  17. memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr));
  18. }
  19. }
  20. /* add a lease into the table, clearing out any old ones */
  21. struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease)
  22. {
  23. struct dhcpOfferedAddr *oldest;
  24. /* clean out any old ones */
  25. clear_lease(chaddr, yiaddr);
  26. oldest = oldest_expired_lease();
  27. if (oldest) {
  28. memcpy(oldest->chaddr, chaddr, 16);
  29. oldest->yiaddr = yiaddr;
  30. oldest->expires = time(0) + lease;
  31. }
  32. return oldest;
  33. }
  34. /* true if a lease has expired */
  35. int lease_expired(struct dhcpOfferedAddr *lease)
  36. {
  37. return (lease->expires < (unsigned long) time(0));
  38. }
  39. /* Find the oldest expired lease, NULL if there are no expired leases */
  40. struct dhcpOfferedAddr *oldest_expired_lease(void)
  41. {
  42. struct dhcpOfferedAddr *oldest = NULL;
  43. unsigned long oldest_lease = time(0);
  44. unsigned int i;
  45. for (i = 0; i < server_config.max_leases; i++)
  46. if (oldest_lease > leases[i].expires) {
  47. oldest_lease = leases[i].expires;
  48. oldest = &(leases[i]);
  49. }
  50. return oldest;
  51. }
  52. /* Find the first lease that matches chaddr, NULL if no match */
  53. struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr)
  54. {
  55. unsigned int i;
  56. for (i = 0; i < server_config.max_leases; i++)
  57. if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]);
  58. return NULL;
  59. }
  60. /* Find the first lease that matches yiaddr, NULL is no match */
  61. struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)
  62. {
  63. unsigned int i;
  64. for (i = 0; i < server_config.max_leases; i++)
  65. if (leases[i].yiaddr == yiaddr) return &(leases[i]);
  66. return NULL;
  67. }
  68. /* check is an IP is taken, if it is, add it to the lease table */
  69. static int check_ip(uint32_t addr)
  70. {
  71. struct in_addr temp;
  72. if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) {
  73. temp.s_addr = addr;
  74. bb_info_msg("%s belongs to someone, reserving it for %ld seconds",
  75. inet_ntoa(temp), server_config.conflict_time);
  76. add_lease(blank_chaddr, addr, server_config.conflict_time);
  77. return 1;
  78. } else return 0;
  79. }
  80. /* find an assignable address, it check_expired is true, we check all the expired leases as well.
  81. * Maybe this should try expired leases by age... */
  82. uint32_t find_address(int check_expired)
  83. {
  84. uint32_t addr, ret;
  85. struct dhcpOfferedAddr *lease = NULL;
  86. addr = ntohl(server_config.start); /* addr is in host order here */
  87. for (;addr <= ntohl(server_config.end); addr++) {
  88. /* ie, 192.168.55.0 */
  89. if (!(addr & 0xFF)) continue;
  90. /* ie, 192.168.55.255 */
  91. if ((addr & 0xFF) == 0xFF) continue;
  92. /* Only do if it isn't an assigned as a static lease */
  93. if (!reservedIp(server_config.static_leases, htonl(addr))) {
  94. /* lease is not taken */
  95. ret = htonl(addr);
  96. lease = find_lease_by_yiaddr(ret);
  97. /* no lease or it expired and we are checking for expired leases */
  98. if ( (!lease || (check_expired && lease_expired(lease)))
  99. && /* and it isn't on the network */ !check_ip(ret)
  100. ) {
  101. return ret;
  102. break;
  103. }
  104. }
  105. }
  106. return 0;
  107. }