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