1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is free software; you can redistribute it and/or modify 4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat it under the terms of the GNU General Public License as published by 5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the Free Software Foundation; version 2 dated June, 1991, or 6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (at your option) version 3 dated 29 June, 2007. 7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is distributed in the hope that it will be useful, 9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat but WITHOUT ANY WARRANTY; without even the implied warranty of 10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GNU General Public License for more details. 12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat You should have received a copy of the GNU General Public License 14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat along with this program. If not, see <http://www.gnu.org/licenses/>. 15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/ 16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include "dnsmasq.h" 18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 19ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP 20ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 21ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic struct dhcp_lease *leases = NULL, *old_leases = NULL; 22ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int dns_dirty, file_dirty, leases_left; 23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_init(time_t now) 25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned long ei; 27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct in_addr addr; 28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int clid_len, hw_len, hw_type; 30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat FILE *leasestream; 31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* These two each hold a DHCP option max size 255 33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat and get a terminating zero added */ 34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->dhcp_buff = safe_malloc(256); 35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->dhcp_buff2 = safe_malloc(256); 36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat leases_left = daemon->dhcp_max; 38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->options & OPT_LEASE_RO) 40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* run "<lease_change_script> init" once to get the 42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat initial state of the database. If leasefile-ro is 43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat set without a script, we just do without any 44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease database. */ 45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SCRIPT 46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->lease_change_command) 47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcpy(daemon->dhcp_buff, daemon->lease_change_command); 49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcat(daemon->dhcp_buff, " init"); 50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat leasestream = popen(daemon->dhcp_buff, "r"); 51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat file_dirty = dns_dirty = 0; 56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* NOTE: need a+ mode to create file if it doesn't exist */ 63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+"); 64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!leasestream) 66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE); 67ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 68ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* a+ mode leaves pointer at end. */ 69ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat rewind(leasestream); 70ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* client-id max length is 255 which is 255*2 digits + 254 colons 73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat borrow DNS packet buffer which is always larger than 1000 bytes */ 74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (leasestream) 75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (fscanf(leasestream, "%lu %255s %16s %255s %764s", 76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat &ei, daemon->dhcp_buff2, daemon->namebuff, 77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->dhcp_buff, daemon->packet) == 5) 78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type); 80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* For backwards compatibility, no explict MAC address type means ether. */ 81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hw_type == 0 && hw_len != 0) 82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat hw_type = ARPHRD_ETHER; 83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.s_addr = inet_addr(daemon->namebuff); 85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* decode hex in place */ 87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat clid_len = 0; 88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (strcmp(daemon->packet, "*") != 0) 89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL); 90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(lease = lease_allocate(addr))) 92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die (_("too many stored leases"), NULL, EC_MISC); 93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_BROKEN_RTC 95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ei != 0) 96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->expires = (time_t)ei + now; 97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->expires = (time_t)0; 99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->length = ei; 100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else 101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* strictly time_t is opaque, but this hack should work on all sane systems, 102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat even when sizeof(time_t) == 8 */ 103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->expires = (time_t)ei; 104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len); 107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (strcmp(daemon->dhcp_buff, "*") != 0) 109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease_set_hostname(lease, daemon->dhcp_buff, 0); 110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* set these correctly: the "old" events are generated later from 112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the startup synthesised SIGHUP. */ 113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->new = lease->changed = 0; 114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SCRIPT 117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!daemon->lease_stream) 118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int rc = 0; 120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* shell returns 127 for "command not found", 126 for bad permissions. */ 122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126) 123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (WEXITSTATUS(rc) == 127) 125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = ENOENT; 126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (WEXITSTATUS(rc) == 126) 127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = EACCES; 128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE); 129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (WEXITSTATUS(rc) != 0) 132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc)); 134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET); 135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Some leases may have expired */ 140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat file_dirty = 0; 141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease_prune(NULL, now); 142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dns_dirty = 1; 143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_update_from_configs(void) 146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* changes to the config may change current leases. */ 148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_config *config; 151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *name; 152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, 155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && 156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (config->flags & CONFIG_NAME) && 157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr)) 158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease_set_hostname(lease, config->hostname, 1); 159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if ((name = host_from_dns(lease->addr))) 160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease_set_hostname(lease, name, 1); /* updates auth flag only */ 161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void ourprintf(int *errp, char *format, ...) 164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_list ap; 166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_start(ap, format); 168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0) 169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *errp = errno; 170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_end(ap); 171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_update_file(time_t now) 174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat time_t next_event; 177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i, err = 0; 178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (file_dirty != 0 && daemon->lease_stream) 180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = 0; 182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat rewind(daemon->lease_stream); 183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0) 184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat err = errno; 185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_BROKEN_RTC 189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, "%u ", lease->length); 190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else 191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, "%lu ", (unsigned long)lease->expires); 192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0) 194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, "%.2x-", lease->hwaddr_type); 195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = 0; i < lease->hwaddr_len; i++) 196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, "%.2x", lease->hwaddr[i]); 198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (i != lease->hwaddr_len - 1) 199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, ":"); 200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, " %s ", inet_ntoa(lease->addr)); 203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*"); 204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->clid && lease->clid_len != 0) 206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = 0; i < lease->clid_len - 1; i++) 208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, "%.2x:", lease->clid[i]); 209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, "%.2x\n", lease->clid[i]); 210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ourprintf(&err, "*\n"); 213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (fflush(daemon->lease_stream) != 0 || 216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fsync(fileno(daemon->lease_stream)) < 0) 217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat err = errno; 218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!err) 220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat file_dirty = 0; 221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Set alarm for when the first lease expires + slop. */ 224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (next_event = 0, lease = leases; lease; lease = lease->next) 225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->expires != 0 && 226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (next_event == 0 || difftime(next_event, lease->expires + 10) > 0.0)) 227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat next_event = lease->expires + 10; 228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (err) 230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0) 232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat next_event = LEASE_RETRY + now; 233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"), 235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->lease_file, strerror(err), 236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (unsigned int)difftime(next_event, now)); 237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (next_event != 0) 240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat alarm((unsigned)difftime(next_event, now)); 241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_update_dns(void) 244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->port != 0 && dns_dirty) 248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_unhash_dhcp(); 250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->fqdn) 254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires); 255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(daemon->options & OPT_DHCP_FQDN) && lease->hostname) 257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires); 258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dns_dirty = 0; 261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_prune(struct dhcp_lease *target, time_t now) 265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease, *tmp, **up; 267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases, up = &leases; lease; lease = tmp) 269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat tmp = lease->next; 271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target) 272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat file_dirty = 1; 274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->hostname) 275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dns_dirty = 1; 276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *up = lease->next; /* unlink */ 278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Put on old_leases list 'till we 280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat can run the script */ 281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->next = old_leases; 282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat old_leases = lease; 283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat leases_left++; 285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat up = &lease->next; 288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type, 293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *clid, int clid_len) 294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (clid) 298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->clid && clid_len == lease->clid_len && 300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcmp(clid, lease->clid, clid_len) == 0) 301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return lease; 302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((!lease->clid || !clid) && 305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat hw_len != 0 && 306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->hwaddr_len == hw_len && 307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->hwaddr_type == hw_type && 308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcmp(hwaddr, lease->hwaddr, hw_len) == 0) 309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return lease; 310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct dhcp_lease *lease_find_by_addr(struct in_addr addr) 315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->addr.s_addr == addr.s_addr) 320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return lease; 321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct dhcp_lease *lease_allocate(struct in_addr addr) 327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease)))) 330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(lease, 0, sizeof(struct dhcp_lease)); 333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->new = 1; 334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->addr = addr; 335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->hwaddr_len = 256; /* illegal value */ 336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->expires = 1; 337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_BROKEN_RTC 338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->length = 0xffffffff; /* illegal value */ 339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->next = leases; 341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat leases = lease; 342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat file_dirty = 1; 344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat leases_left--; 345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return lease; 347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now) 350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat time_t exp = now + (time_t)len; 352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (len == 0xffffffff) 354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat exp = 0; 356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat len = 0; 357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (exp != lease->expires) 360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dns_dirty = 1; 362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->expires = exp; 363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_BROKEN_RTC 364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->aux_changed = file_dirty = 1; 365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_BROKEN_RTC 369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (len != lease->length) 370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->length = len; 372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->aux_changed = file_dirty = 1; 373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr, 378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *clid, int hw_len, int hw_type, int clid_len) 379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hw_len != lease->hwaddr_len || 381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat hw_type != lease->hwaddr_type || 382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0)) 383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(lease->hwaddr, hwaddr, hw_len); 385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->hwaddr_len = hw_len; 386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->hwaddr_type = hw_type; 387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->changed = file_dirty = 1; /* run script on change */ 388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* only update clid when one is available, stops packets 391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat without a clid removing the record. Lease init uses 392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat clid_len == 0 for no clid. */ 393ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (clid_len != 0 && clid) 394ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!lease->clid) 396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->clid_len = 0; 397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->clid_len != clid_len) 399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->aux_changed = file_dirty = 1; 401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->clid); 402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(lease->clid = whine_malloc(clid_len))) 403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (memcmp(lease->clid, clid, clid_len) != 0) 406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->aux_changed = file_dirty = 1; 407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->clid_len = clid_len; 409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(lease->clid, clid, clid_len); 410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void kill_name(struct dhcp_lease *lease) 415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* run script to say we lost our old name */ 417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* this shouldn't happen unless updates are very quick and the 419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat script very slow, we just avoid a memory leak if it does. */ 420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->old_hostname); 421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If we know the fqdn, pass that. The helper will derive the 423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unqualified name from it, free the unqulaified name here. */ 424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->fqdn) 426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->old_hostname = lease->fqdn; 428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->hostname); 429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->old_hostname = lease->hostname; 432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->hostname = lease->fqdn = NULL; 434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_set_hostname(struct dhcp_lease *lease, char *name, int auth) 437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease_tmp; 439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *new_name = NULL, *new_fqdn = NULL; 440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->hostname && name && hostname_isequal(lease->hostname, name)) 442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->auth_name = auth; 444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!name && !lease->hostname) 448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If a machine turns up on a new net without dropping the old lease, 451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat or two machines claim the same name, then we end up with two interfaces with 452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the same name. Check for that here and remove the name from the old lease. 453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Don't allow a name from the client to override a name from dnsmasq config. */ 454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (name) 456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((new_name = whine_malloc(strlen(name) + 1))) 458ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *suffix = get_domain(lease->addr); 460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcpy(new_name, name); 461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (suffix && (new_fqdn = whine_malloc(strlen(new_name) + strlen(suffix) + 2))) 462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcpy(new_fqdn, name); 464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcat(new_fqdn, "."); 465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcat(new_fqdn, suffix); 466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Depending on mode, we check either unqualified name or FQDN. */ 470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next) 471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->options & OPT_DHCP_FQDN) 473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn) ) 475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) ) 480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease_tmp->auth_name && !auth) 484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(new_name); 486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(new_fqdn); 487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat kill_name(lease_tmp); 491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->hostname) 496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat kill_name(lease); 497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->hostname = new_name; 499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->fqdn = new_fqdn; 500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->auth_name = auth; 501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat file_dirty = 1; 503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dns_dirty = 1; 504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->changed = 1; /* run script on change */ 505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid lease_set_interface(struct dhcp_lease *lease, int interface) 508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->last_interface == interface) 510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->last_interface = interface; 513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->changed = 1; 514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 515ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 516ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid rerun_scripts(void) 517ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 518ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 519ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 520ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 521ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->changed = 1; 522ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 523ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 524ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* deleted leases get transferred to the old_leases list. 525ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat remove them here, after calling the lease change 526ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat script. Also run the lease change script on new/modified leases. 527ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 528ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Return zero if nothing to do. */ 529ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint do_script_run(time_t now) 530ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 531ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_lease *lease; 532ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 533ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DBUS 534ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If we're going to be sending DBus signals, but the connection is not yet up, 535ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat delay everything until it is. */ 536ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((daemon->options & OPT_DBUS) && !daemon->dbus) 537ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 538ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 539ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 540ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (old_leases) 541ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 542ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease = old_leases; 543ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 544ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If the lease still has an old_hostname, do the "old" action on that first */ 545ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->old_hostname) 546ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 547ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SCRIPT 548ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now); 549ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 550ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->old_hostname); 551ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->old_hostname = NULL; 552ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 553ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 554ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 555ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat kill_name(lease); 557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SCRIPT 558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat queue_script(ACTION_DEL, lease, lease->old_hostname, now); 559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 560ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DBUS 561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname); 562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat old_leases = lease->next; 564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 565ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->old_hostname); 566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->clid); 567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->vendorclass); 568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->userclass); 569ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->supplied_hostname); 570ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease); 571ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* make sure we announce the loss of a hostname before its new location. */ 577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->old_hostname) 579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SCRIPT 581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now); 582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->old_hostname); 584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->old_hostname = NULL; 585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lease = leases; lease; lease = lease->next) 589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lease->new || lease->changed || 590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (lease->aux_changed && (daemon->options & OPT_LEASE_RO))) 591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SCRIPT 593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, 594ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->fqdn ? lease->fqdn : lease->hostname, now); 595ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 596ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DBUS 597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat emit_dbus_signal(lease->new ? ACTION_ADD : ACTION_OLD, lease, 598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->fqdn ? lease->fqdn : lease->hostname); 599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->new = lease->changed = lease->aux_changed = 0; 601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* these are used for the "add" call, then junked, since they're not in the database */ 603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->vendorclass); 604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->vendorclass = NULL; 605ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 606ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->userclass); 607ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->userclass = NULL; 608ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 609ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(lease->supplied_hostname); 610ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lease->supplied_hostname = NULL; 611ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 612ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 613ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 614ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 615ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* nothing to do */ 616ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 617ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 618ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 619ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 620ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 621ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 622ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 623