1/* 2 * leases.c -- tools to manage DHCP leases 3 * Russ Dill <Russ.Dill@asu.edu> July 2001 4 */ 5 6#include <time.h> 7#include <string.h> 8#include <sys/socket.h> 9#include <netinet/in.h> 10#include <arpa/inet.h> 11 12#include "debug.h" 13#include "dhcpd.h" 14#include "files.h" 15#include "options.h" 16#include "leases.h" 17#include "arpping.h" 18 19#include <bcmnvram.h> 20 21int check_lan_ip(u_int32_t addr); 22 23unsigned char blank_chaddr[] = {[0 ... 15] = 0}; 24struct dhcpOfferedAddr *static_lease; 25 26/* clear every lease out that chaddr OR yiaddr matches and is nonzero */ 27void clear_lease(u_int8_t *chaddr, u_int32_t yiaddr) 28{ 29 unsigned int i, j; 30 31 //added by Joey to handle static lease 32 static_lease = NULL; 33 34 for (j = 0; j < 16 && !chaddr[j]; j++); 35 36 for (i = 0; i < server_config.max_leases; i++) 37 { 38 // added by Joey to handle static lease 39 //if (memcmp(leases[i].chaddr, chaddr, 16)==0 && leases[i].expires==0xffffffff) 40 // static_lease = &leases[i]; 41 42 if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) || 43 (yiaddr && leases[i].yiaddr == yiaddr)) 44 { 45 if (leases[i].expires==0xffffffff) static_lease=&leases[i]; 46 else memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr)); 47 } 48 } 49} 50 51 52/* add a lease into the table, clearing out any old ones */ 53struct dhcpOfferedAddr *add_lease(u_int8_t *chaddr, u_int32_t yiaddr, unsigned long lease) 54{ 55 struct dhcpOfferedAddr *oldest; 56 57 /* clean out any old ones */ 58 clear_lease(chaddr, yiaddr); 59 60 // added by Joey to handle static lease 61 if (static_lease) return(static_lease); 62 63 oldest = oldest_expired_lease(); 64 65 if (oldest) { 66 memcpy(oldest->chaddr, chaddr, 16); 67 oldest->yiaddr = yiaddr; 68 if (lease==0xffffffff) 69 oldest->expires = 0xffffffff; 70 else 71 oldest->expires = time(0) + lease; 72 } 73 74 return oldest; 75} 76 77 78/* true if a lease has expired */ 79int lease_expired(struct dhcpOfferedAddr *lease) 80{ 81 return (lease->expires < (unsigned long) time(0)); 82} 83 84 85/* Find the oldest expired lease, NULL if there are no expired leases */ 86struct dhcpOfferedAddr *oldest_expired_lease(void) 87{ 88 struct dhcpOfferedAddr *oldest = NULL; 89 unsigned long oldest_lease = time(0); 90 unsigned int i; 91 92 93 for (i = 0; i < server_config.max_leases; i++) 94 if (oldest_lease > leases[i].expires) { 95 oldest_lease = leases[i].expires; 96 oldest = &(leases[i]); 97 } 98 return oldest; 99 100} 101 102 103/* Find the first lease that matches chaddr, NULL if no match */ 104struct dhcpOfferedAddr *find_lease_by_chaddr(u_int8_t *chaddr) 105{ 106 unsigned int i; 107 108 for (i = 0; i < server_config.max_leases; i++) 109 //JYWeng: 20030701 for palm: chaddr error after first 6 bytes 110 //if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]); 111 if (!memcmp(leases[i].chaddr, chaddr, 6)) return &(leases[i]); 112 113 return NULL; 114} 115 116 117/* Find the first lease that matches yiaddr, NULL is no match */ 118struct dhcpOfferedAddr *find_lease_by_yiaddr(u_int32_t yiaddr) 119{ 120 unsigned int i; 121 122 for (i = 0; i < server_config.max_leases; i++) 123 if (leases[i].yiaddr == yiaddr) return &(leases[i]); 124 125 return NULL; 126} 127 128 129/* find an assignable address, it check_expired is true, we check all the expired leases as well. 130 * Maybe this should try expired leases by age... */ 131u_int32_t find_address(int check_expired) 132{ 133 u_int32_t addr, ret; 134 struct dhcpOfferedAddr *lease = NULL; 135 136 addr = ntohl(server_config.start); /* addr is in host order here */ 137 for (;addr <= ntohl(server_config.end); addr++) { 138 139 /* ie, 192.168.55.0 */ 140 if (!(addr & 0xFF)) continue; 141 142 /* ie, 192.168.55.255 */ 143 if ((addr & 0xFF) == 0xFF) continue; 144 145 /* lease is not taken */ 146 ret = htonl(addr); 147 if ((!(lease = find_lease_by_yiaddr(ret)) || 148 /* or it expired and we are checking for expired leases */ 149 (check_expired && lease_expired(lease))) && 150 /* and it isn't on the network */ 151 !check_ip(ret) && 152 /* and different from LAN IP */ 153 check_lan_ip(ret)) { 154 return ret; 155 } 156 } 157 return 0; 158} 159 160 161/* check is an IP is taken, if it is, add it to the lease table */ 162int check_ip(u_int32_t addr) 163{ 164 struct in_addr temp; 165 166 if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) { 167 temp.s_addr = addr; 168 LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds", 169 inet_ntoa(temp), server_config.conflict_time); 170 add_lease(blank_chaddr, addr, server_config.conflict_time); 171 return 1; 172 } else return 0; 173} 174 175/* check is an IP is used by LAN IP */ 176int check_lan_ip(u_int32_t addr) 177{ 178 struct in_addr temp; 179 temp.s_addr = addr; 180 181 if (nvram_match("lan_ipaddr_t", inet_ntoa(temp))) 182 return 0; 183 else 184 return 1; 185} 186