]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/lease.c
Accumulated 2.60 changes going into git
[people/ms/dnsmasq.git] / src / lease.c
CommitLineData
28866e95 1/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
9e4abcb5
SK
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
824af85b
SK
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
9e4abcb5
SK
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.
824af85b 12
73a08a24
SK
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/>.
9e4abcb5
SK
15*/
16
9e4abcb5
SK
17#include "dnsmasq.h"
18
7622fc06
SK
19#ifdef HAVE_DHCP
20
5aabfc78 21static struct dhcp_lease *leases = NULL, *old_leases = NULL;
5e9e0efb 22static int dns_dirty, file_dirty, leases_left;
9e4abcb5 23
5aabfc78 24void lease_init(time_t now)
9e4abcb5 25{
9e4abcb5 26 unsigned long ei;
c72daea8 27 struct all_addr addr;
9e4abcb5 28 struct dhcp_lease *lease;
5aabfc78 29 int clid_len, hw_len, hw_type;
208b65c5 30 FILE *leasestream;
c72daea8
SK
31#ifdef HAVE_DHCP6
32 int v6pass = 0;
33#endif
5e9e0efb 34
8ef5ada2 35 /* These each hold a DHCP option max size 255
5aabfc78
SK
36 and get a terminating zero added */
37 daemon->dhcp_buff = safe_malloc(256);
38 daemon->dhcp_buff2 = safe_malloc(256);
8ef5ada2
SK
39 daemon->dhcp_buff3 = safe_malloc(256);
40
3be34541 41 leases_left = daemon->dhcp_max;
44a2a316 42
28866e95 43 if (option_bool(OPT_LEASE_RO))
208b65c5
SK
44 {
45 /* run "<lease_change_script> init" once to get the
46 initial state of the database. If leasefile-ro is
47 set without a script, we just do without any
48 lease database. */
1f15b81d
SK
49#ifdef HAVE_SCRIPT
50 if (daemon->lease_change_command)
208b65c5 51 {
1f15b81d
SK
52 strcpy(daemon->dhcp_buff, daemon->lease_change_command);
53 strcat(daemon->dhcp_buff, " init");
54 leasestream = popen(daemon->dhcp_buff, "r");
208b65c5 55 }
1f15b81d
SK
56 else
57#endif
58 {
59 file_dirty = dns_dirty = 0;
60 return;
61 }
62
208b65c5
SK
63 }
64 else
65 {
66 /* NOTE: need a+ mode to create file if it doesn't exist */
67 leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
68
69 if (!leasestream)
5aabfc78 70 die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
208b65c5 71
7622fc06 72 /* a+ mode leaves pointer at end. */
208b65c5
SK
73 rewind(leasestream);
74 }
7cebd20f 75
c72daea8
SK
76#ifdef HAVE_DHCP6
77 again:
78#endif
79
0a852541
SK
80 /* client-id max length is 255 which is 255*2 digits + 254 colons
81 borrow DNS packet buffer which is always larger than 1000 bytes */
208b65c5 82 if (leasestream)
c72daea8 83 while (fscanf(leasestream, "%lu %255s %64s %255s %764s",
208b65c5
SK
84 &ei, daemon->dhcp_buff2, daemon->namebuff,
85 daemon->dhcp_buff, daemon->packet) == 5)
86 {
c72daea8
SK
87#ifdef HAVE_DHCP6
88 if (!v6pass)
89#endif
90 {
91 hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
92 /* For backwards compatibility, no explict MAC address type means ether. */
93 if (hw_type == 0 && hw_len != 0)
94 hw_type = ARPHRD_ETHER;
95 }
96
97#ifdef HAVE_DHCP6
98 if (v6pass)
99 inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6);
100 else
101#endif
102 inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4);
103
208b65c5
SK
104 clid_len = 0;
105 if (strcmp(daemon->packet, "*") != 0)
106 clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
107
c72daea8
SK
108#ifdef HAVE_DHCP6
109 if (v6pass)
110 lease = lease_allocate6(&addr.addr.addr6);
111 else
112#endif
113 lease = lease_allocate4(addr.addr.addr4);
114
115 if (!lease)
5aabfc78
SK
116 die (_("too many stored leases"), NULL, EC_MISC);
117
5e9e0efb 118#ifdef HAVE_BROKEN_RTC
208b65c5
SK
119 if (ei != 0)
120 lease->expires = (time_t)ei + now;
121 else
122 lease->expires = (time_t)0;
123 lease->length = ei;
5e9e0efb 124#else
208b65c5
SK
125 /* strictly time_t is opaque, but this hack should work on all sane systems,
126 even when sizeof(time_t) == 8 */
127 lease->expires = (time_t)ei;
5e9e0efb 128#endif
c72daea8
SK
129
130#ifdef HAVE_DHCP6
131 if (!v6pass)
132#endif
133 lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
208b65c5
SK
134
135 if (strcmp(daemon->dhcp_buff, "*") != 0)
1f15b81d 136 lease_set_hostname(lease, daemon->dhcp_buff, 0);
5aabfc78
SK
137
138 /* set these correctly: the "old" events are generated later from
139 the startup synthesised SIGHUP. */
140 lease->new = lease->changed = 0;
208b65c5 141 }
c72daea8
SK
142
143#ifdef HAVE_DHCP6
144 if (!v6pass)
145 {
146 if (fscanf(leasestream, "duid %255s", daemon->dhcp_buff) == 1)
147 {
148 daemon->duid_len = parse_hex(daemon->dhcp_buff, (unsigned char *)daemon->dhcp_buff, 130, NULL, NULL);
149 daemon->duid = safe_malloc(daemon->duid_len);
150 memcpy(daemon->duid, daemon->dhcp_buff, daemon->duid_len );
151 v6pass = 1;
152 goto again;
153 }
154
155 /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
156 if (daemon->dhcp6)
157 make_duid(now);
158 }
159#endif
208b65c5 160
1f15b81d 161#ifdef HAVE_SCRIPT
208b65c5
SK
162 if (!daemon->lease_stream)
163 {
164 int rc = 0;
9e4abcb5 165
208b65c5
SK
166 /* shell returns 127 for "command not found", 126 for bad permissions. */
167 if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126)
168 {
169 if (WEXITSTATUS(rc) == 127)
170 errno = ENOENT;
171 else if (WEXITSTATUS(rc) == 126)
172 errno = EACCES;
5aabfc78 173 die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
208b65c5
SK
174 }
175
176 if (WEXITSTATUS(rc) != 0)
177 {
178 sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
5aabfc78 179 die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
208b65c5 180 }
9e4abcb5 181 }
1f15b81d 182#endif
7cebd20f
SK
183
184 /* Some leases may have expired */
185 file_dirty = 0;
186 lease_prune(NULL, now);
187 dns_dirty = 1;
44a2a316
SK
188}
189
5aabfc78 190void lease_update_from_configs(void)
44a2a316
SK
191{
192 /* changes to the config may change current leases. */
193
194 struct dhcp_lease *lease;
195 struct dhcp_config *config;
b8187c80
SK
196 char *name;
197
9e4abcb5 198 for (lease = leases; lease; lease = lease->next)
cdeda28f
SK
199 if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len,
200 lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
b8187c80
SK
201 (config->flags & CONFIG_NAME) &&
202 (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
9009d746 203 lease_set_hostname(lease, config->hostname, 1);
5aabfc78 204 else if ((name = host_from_dns(lease->addr)))
9009d746 205 lease_set_hostname(lease, name, 1); /* updates auth flag only */
9e4abcb5
SK
206}
207
5aabfc78 208static void ourprintf(int *errp, char *format, ...)
9e4abcb5 209{
7cebd20f 210 va_list ap;
5e9e0efb 211
7cebd20f
SK
212 va_start(ap, format);
213 if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0)
214 *errp = errno;
215 va_end(ap);
216}
217
5aabfc78 218void lease_update_file(time_t now)
7cebd20f
SK
219{
220 struct dhcp_lease *lease;
221 time_t next_event;
222 int i, err = 0;
223
208b65c5 224 if (file_dirty != 0 && daemon->lease_stream)
9e4abcb5 225 {
cdeda28f
SK
226 errno = 0;
227 rewind(daemon->lease_stream);
228 if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0)
7cebd20f 229 err = errno;
9e4abcb5
SK
230
231 for (lease = leases; lease; lease = lease->next)
232 {
c72daea8
SK
233
234#ifdef HAVE_DHCP6
235 if (lease->is_ipv6)
236 continue;
237#endif
238
44a2a316 239#ifdef HAVE_BROKEN_RTC
5aabfc78 240 ourprintf(&err, "%u ", lease->length);
44a2a316 241#else
5aabfc78 242 ourprintf(&err, "%lu ", (unsigned long)lease->expires);
5e9e0efb 243#endif
c72daea8 244
7cebd20f 245 if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0)
5aabfc78 246 ourprintf(&err, "%.2x-", lease->hwaddr_type);
5e9e0efb
SK
247 for (i = 0; i < lease->hwaddr_len; i++)
248 {
5aabfc78 249 ourprintf(&err, "%.2x", lease->hwaddr[i]);
7cebd20f 250 if (i != lease->hwaddr_len - 1)
5aabfc78 251 ourprintf(&err, ":");
5e9e0efb 252 }
c72daea8
SK
253
254 inet_ntop(AF_INET, &lease->addr, daemon->addrbuff, ADDRSTRLEN);
5aabfc78 255
c72daea8 256 ourprintf(&err, " %s ", daemon->addrbuff);
1f15b81d
SK
257 ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
258
0a852541 259 if (lease->clid && lease->clid_len != 0)
9e4abcb5
SK
260 {
261 for (i = 0; i < lease->clid_len - 1; i++)
5aabfc78
SK
262 ourprintf(&err, "%.2x:", lease->clid[i]);
263 ourprintf(&err, "%.2x\n", lease->clid[i]);
9e4abcb5
SK
264 }
265 else
5aabfc78 266 ourprintf(&err, "*\n");
9e4abcb5 267 }
7cebd20f 268
c72daea8
SK
269#ifdef HAVE_DHCP6
270 if (daemon->duid)
271 {
272 ourprintf(&err, "duid ");
273 for (i = 0; i < daemon->duid_len - 1; i++)
274 ourprintf(&err, "%.2x:", daemon->duid[i]);
275 ourprintf(&err, "%.2x\n", daemon->duid[i]);
276
277 for (lease = leases; lease; lease = lease->next)
278 {
279
280 if (!lease->is_ipv6)
281 continue;
282
283#ifdef HAVE_BROKEN_RTC
284 ourprintf(&err, "%u ", lease->length);
285#else
286 ourprintf(&err, "%lu ", (unsigned long)lease->expires);
287#endif
288
289 inet_ntop(AF_INET6, lease->hwaddr, daemon->addrbuff, ADDRSTRLEN);
290
291 ourprintf(&err, "* %s ", daemon->addrbuff);
292 ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
293
294 if (lease->clid && lease->clid_len != 0)
295 {
296 for (i = 0; i < lease->clid_len - 1; i++)
297 ourprintf(&err, "%.2x:", lease->clid[i]);
298 ourprintf(&err, "%.2x\n", lease->clid[i]);
299 }
300 else
301 ourprintf(&err, "*\n");
302 }
303 }
304#endif
305
7cebd20f
SK
306 if (fflush(daemon->lease_stream) != 0 ||
307 fsync(fileno(daemon->lease_stream)) < 0)
308 err = errno;
309
310 if (!err)
311 file_dirty = 0;
312 }
313
314 /* Set alarm for when the first lease expires + slop. */
315 for (next_event = 0, lease = leases; lease; lease = lease->next)
316 if (lease->expires != 0 &&
317 (next_event == 0 || difftime(next_event, lease->expires + 10) > 0.0))
318 next_event = lease->expires + 10;
319
320 if (err)
321 {
322 if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
323 next_event = LEASE_RETRY + now;
324
7622fc06 325 my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"),
f2621c7f
SK
326 daemon->lease_file, strerror(err),
327 (unsigned int)difftime(next_event, now));
9e4abcb5 328 }
7cebd20f
SK
329
330 if (next_event != 0)
331 alarm((unsigned)difftime(next_event, now));
44a2a316 332}
9e4abcb5 333
5aabfc78 334void lease_update_dns(void)
44a2a316
SK
335{
336 struct dhcp_lease *lease;
337
824af85b 338 if (daemon->port != 0 && dns_dirty)
9e4abcb5
SK
339 {
340 cache_unhash_dhcp();
44a2a316 341
9e4abcb5
SK
342 for (lease = leases; lease; lease = lease->next)
343 {
9009d746
SK
344 if (lease->fqdn)
345 cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
346
28866e95 347 if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
9009d746 348 cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
9e4abcb5
SK
349 }
350
351 dns_dirty = 0;
352 }
353}
354
355void lease_prune(struct dhcp_lease *target, time_t now)
356{
357 struct dhcp_lease *lease, *tmp, **up;
358
359 for (lease = leases, up = &leases; lease; lease = tmp)
360 {
361 tmp = lease->next;
362 if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target)
363 {
5e9e0efb 364 file_dirty = 1;
9e4abcb5 365 if (lease->hostname)
7cebd20f
SK
366 dns_dirty = 1;
367
c72daea8 368 *up = lease->next; /* unlink */
7cebd20f
SK
369
370 /* Put on old_leases list 'till we
371 can run the script */
372 lease->next = old_leases;
373 old_leases = lease;
374
44a2a316 375 leases_left++;
9e4abcb5
SK
376 }
377 else
378 up = &lease->next;
379 }
380}
381
382
cdeda28f 383struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
0a852541 384 unsigned char *clid, int clid_len)
9e4abcb5 385{
9e4abcb5
SK
386 struct dhcp_lease *lease;
387
0a852541
SK
388 if (clid)
389 for (lease = leases; lease; lease = lease->next)
c72daea8
SK
390 {
391#ifdef HAVE_DHCP6
392 if (lease->is_ipv6)
393 continue;
394#endif
395 if (lease->clid && clid_len == lease->clid_len &&
396 memcmp(clid, lease->clid, clid_len) == 0)
397 return lease;
398 }
0a852541
SK
399
400 for (lease = leases; lease; lease = lease->next)
c72daea8
SK
401 {
402#ifdef HAVE_DHCP6
403 if (lease->is_ipv6)
404 continue;
405#endif
406 if ((!lease->clid || !clid) &&
407 hw_len != 0 &&
408 lease->hwaddr_len == hw_len &&
409 lease->hwaddr_type == hw_type &&
410 memcmp(hwaddr, lease->hwaddr, hw_len) == 0)
411 return lease;
412 }
413
9e4abcb5
SK
414 return NULL;
415}
416
417struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
418{
419 struct dhcp_lease *lease;
420
421 for (lease = leases; lease; lease = lease->next)
c72daea8
SK
422 {
423#ifdef HAVE_DHCP6
424 if (lease->is_ipv6)
425 continue;
426#endif
427 if (lease->addr.s_addr == addr.s_addr)
428 return lease;
429 }
430
9e4abcb5
SK
431 return NULL;
432}
433
7de060b0
SK
434/* Find largest assigned address in context */
435struct in_addr lease_find_max_addr(struct dhcp_context *context)
436{
437 struct dhcp_lease *lease;
438 struct in_addr addr = context->start;
439
440 if (!(context->flags & (CONTEXT_STATIC | CONTEXT_PROXY)))
441 for (lease = leases; lease; lease = lease->next)
c72daea8
SK
442 {
443#ifdef HAVE_DHCP6
444 if (lease->is_ipv6)
445 continue;
446#endif
447 if (((unsigned)ntohl(lease->addr.s_addr)) > ((unsigned)ntohl(context->start.s_addr)) &&
448 ((unsigned)ntohl(lease->addr.s_addr)) <= ((unsigned)ntohl(context->end.s_addr)) &&
449 ((unsigned)ntohl(lease->addr.s_addr)) > ((unsigned)ntohl(addr.s_addr)))
450 addr = lease->addr;
451 }
7de060b0
SK
452
453 return addr;
454}
9e4abcb5 455
c72daea8 456static struct dhcp_lease *lease_allocate(void)
9e4abcb5
SK
457{
458 struct dhcp_lease *lease;
5aabfc78 459 if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease))))
9e4abcb5
SK
460 return NULL;
461
7cebd20f
SK
462 memset(lease, 0, sizeof(struct dhcp_lease));
463 lease->new = 1;
9e4abcb5 464 lease->expires = 1;
5e9e0efb
SK
465#ifdef HAVE_BROKEN_RTC
466 lease->length = 0xffffffff; /* illegal value */
467#endif
9e4abcb5
SK
468 lease->next = leases;
469 leases = lease;
470
5e9e0efb 471 file_dirty = 1;
44a2a316 472 leases_left--;
9e4abcb5
SK
473
474 return lease;
475}
476
c72daea8
SK
477struct dhcp_lease *lease_allocate4(struct in_addr addr)
478{
479 struct dhcp_lease *lease = lease_allocate();
480 lease->addr = addr;
481 lease->hwaddr_len = 256; /* illegal value */
482
483 return lease;
484}
485
486#ifdef HAVE_DHCP6
487struct dhcp_lease *lease_allocate6(struct in6_addr *addrp)
488{
489 struct dhcp_lease *lease = lease_allocate();
490 memcpy(lease->hwaddr, addrp, sizeof(*addrp)) ;
491 lease->is_ipv6 = 1;
492
493 return lease;
494}
495#endif
496
5e9e0efb 497void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
9e4abcb5 498{
5e9e0efb
SK
499 time_t exp = now + (time_t)len;
500
501 if (len == 0xffffffff)
502 {
503 exp = 0;
504 len = 0;
505 }
506
9e4abcb5 507 if (exp != lease->expires)
0a852541 508 {
0a852541 509 dns_dirty = 1;
5e9e0efb
SK
510 lease->expires = exp;
511#ifndef HAVE_BROKEN_RTC
208b65c5 512 lease->aux_changed = file_dirty = 1;
5e9e0efb 513#endif
0a852541 514 }
5e9e0efb
SK
515
516#ifdef HAVE_BROKEN_RTC
517 if (len != lease->length)
518 {
519 lease->length = len;
208b65c5 520 lease->aux_changed = file_dirty = 1;
5e9e0efb
SK
521 }
522#endif
523}
9e4abcb5 524
7cebd20f 525void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
cdeda28f 526 unsigned char *clid, int hw_len, int hw_type, int clid_len)
9e4abcb5 527{
cdeda28f
SK
528 if (hw_len != lease->hwaddr_len ||
529 hw_type != lease->hwaddr_type ||
7cebd20f 530 (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
9e4abcb5 531 {
cdeda28f
SK
532 memcpy(lease->hwaddr, hwaddr, hw_len);
533 lease->hwaddr_len = hw_len;
534 lease->hwaddr_type = hw_type;
208b65c5 535 lease->changed = file_dirty = 1; /* run script on change */
9e4abcb5 536 }
0a852541
SK
537
538 /* only update clid when one is available, stops packets
539 without a clid removing the record. Lease init uses
540 clid_len == 0 for no clid. */
541 if (clid_len != 0 && clid)
542 {
543 if (!lease->clid)
544 lease->clid_len = 0;
545
546 if (lease->clid_len != clid_len)
547 {
208b65c5 548 lease->aux_changed = file_dirty = 1;
5aabfc78
SK
549 free(lease->clid);
550 if (!(lease->clid = whine_malloc(clid_len)))
7cebd20f 551 return;
0a852541
SK
552 }
553 else if (memcmp(lease->clid, clid, clid_len) != 0)
208b65c5
SK
554 lease->aux_changed = file_dirty = 1;
555
0a852541
SK
556 lease->clid_len = clid_len;
557 memcpy(lease->clid, clid, clid_len);
558 }
208b65c5 559
9e4abcb5
SK
560}
561
9009d746
SK
562static void kill_name(struct dhcp_lease *lease)
563{
564 /* run script to say we lost our old name */
565
566 /* this shouldn't happen unless updates are very quick and the
567 script very slow, we just avoid a memory leak if it does. */
568 free(lease->old_hostname);
569
570 /* If we know the fqdn, pass that. The helper will derive the
571 unqualified name from it, free the unqulaified name here. */
572
573 if (lease->fqdn)
574 {
575 lease->old_hostname = lease->fqdn;
576 free(lease->hostname);
577 }
578 else
579 lease->old_hostname = lease->hostname;
580
581 lease->hostname = lease->fqdn = NULL;
582}
583
584void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth)
9e4abcb5
SK
585{
586 struct dhcp_lease *lease_tmp;
587 char *new_name = NULL, *new_fqdn = NULL;
9009d746 588
a222641c 589 if (lease->hostname && name && hostname_isequal(lease->hostname, name))
b8187c80
SK
590 {
591 lease->auth_name = auth;
592 return;
593 }
7cebd20f 594
9e4abcb5
SK
595 if (!name && !lease->hostname)
596 return;
597
598 /* If a machine turns up on a new net without dropping the old lease,
599 or two machines claim the same name, then we end up with two interfaces with
b8187c80
SK
600 the same name. Check for that here and remove the name from the old lease.
601 Don't allow a name from the client to override a name from dnsmasq config. */
9e4abcb5
SK
602
603 if (name)
604 {
9009d746
SK
605 if ((new_name = whine_malloc(strlen(name) + 1)))
606 {
607 char *suffix = get_domain(lease->addr);
608 strcpy(new_name, name);
609 if (suffix && (new_fqdn = whine_malloc(strlen(new_name) + strlen(suffix) + 2)))
610 {
611 strcpy(new_fqdn, name);
612 strcat(new_fqdn, ".");
613 strcat(new_fqdn, suffix);
614 }
615 }
616
617 /* Depending on mode, we check either unqualified name or FQDN. */
9e4abcb5 618 for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
9e4abcb5 619 {
28866e95 620 if (option_bool(OPT_DHCP_FQDN))
9009d746
SK
621 {
622 if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn) )
623 continue;
624 }
625 else
626 {
627 if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) )
628 continue;
629 }
630
631 if (lease_tmp->auth_name && !auth)
632 {
633 free(new_name);
634 free(new_fqdn);
635 return;
636 }
637
638 kill_name(lease_tmp);
639 break;
9e4abcb5
SK
640 }
641 }
642
643 if (lease->hostname)
9009d746 644 kill_name(lease);
1697269c 645
9e4abcb5
SK
646 lease->hostname = new_name;
647 lease->fqdn = new_fqdn;
b8187c80 648 lease->auth_name = auth;
9e4abcb5 649
5e9e0efb 650 file_dirty = 1;
7cebd20f 651 dns_dirty = 1;
208b65c5 652 lease->changed = 1; /* run script on change */
7cebd20f
SK
653}
654
824af85b
SK
655void lease_set_interface(struct dhcp_lease *lease, int interface)
656{
657 if (lease->last_interface == interface)
658 return;
659
660 lease->last_interface = interface;
661 lease->changed = 1;
662}
663
5aabfc78
SK
664void rerun_scripts(void)
665{
666 struct dhcp_lease *lease;
667
668 for (lease = leases; lease; lease = lease->next)
669 lease->changed = 1;
670}
671
7cebd20f
SK
672/* deleted leases get transferred to the old_leases list.
673 remove them here, after calling the lease change
1697269c
SK
674 script. Also run the lease change script on new/modified leases.
675
676 Return zero if nothing to do. */
5aabfc78 677int do_script_run(time_t now)
7cebd20f
SK
678{
679 struct dhcp_lease *lease;
9e4abcb5 680
9009d746
SK
681#ifdef HAVE_DBUS
682 /* If we're going to be sending DBus signals, but the connection is not yet up,
683 delay everything until it is. */
28866e95 684 if (option_bool(OPT_DBUS) && !daemon->dbus)
9009d746
SK
685 return 0;
686#endif
687
1697269c 688 if (old_leases)
7cebd20f 689 {
7cebd20f 690 lease = old_leases;
1697269c
SK
691
692 /* If the lease still has an old_hostname, do the "old" action on that first */
693 if (lease->old_hostname)
694 {
1f15b81d 695#ifdef HAVE_SCRIPT
5aabfc78
SK
696 queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
697#endif
1697269c
SK
698 free(lease->old_hostname);
699 lease->old_hostname = NULL;
700 return 1;
701 }
702 else
703 {
9009d746 704 kill_name(lease);
1f15b81d 705#ifdef HAVE_SCRIPT
9009d746 706 queue_script(ACTION_DEL, lease, lease->old_hostname, now);
1f15b81d
SK
707#endif
708#ifdef HAVE_DBUS
709 emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
5aabfc78 710#endif
1697269c
SK
711 old_leases = lease->next;
712
9009d746 713 free(lease->old_hostname);
5aabfc78 714 free(lease->clid);
316e2730 715 free(lease->extradata);
1697269c
SK
716 free(lease);
717
718 return 1;
719 }
7cebd20f 720 }
1697269c
SK
721
722 /* make sure we announce the loss of a hostname before its new location. */
723 for (lease = leases; lease; lease = lease->next)
724 if (lease->old_hostname)
725 {
1f15b81d 726#ifdef HAVE_SCRIPT
5aabfc78
SK
727 queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
728#endif
1697269c
SK
729 free(lease->old_hostname);
730 lease->old_hostname = NULL;
731 return 1;
732 }
733
7cebd20f 734 for (lease = leases; lease; lease = lease->next)
208b65c5 735 if (lease->new || lease->changed ||
28866e95 736 (lease->aux_changed && option_bool(OPT_LEASE_RO)))
7cebd20f 737 {
1f15b81d 738#ifdef HAVE_SCRIPT
9009d746
SK
739 queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease,
740 lease->fqdn ? lease->fqdn : lease->hostname, now);
1f15b81d
SK
741#endif
742#ifdef HAVE_DBUS
743 emit_dbus_signal(lease->new ? ACTION_ADD : ACTION_OLD, lease,
744 lease->fqdn ? lease->fqdn : lease->hostname);
5aabfc78 745#endif
208b65c5 746 lease->new = lease->changed = lease->aux_changed = 0;
1697269c 747
316e2730
SK
748 /* this is used for the "add" call, then junked, since they're not in the database */
749 free(lease->extradata);
750 lease->extradata = NULL;
1697269c
SK
751
752 return 1;
7cebd20f 753 }
1697269c
SK
754
755 return 0; /* nothing to do */
7cebd20f 756}
7622fc06
SK
757
758#endif
7cebd20f
SK
759
760
761
9e4abcb5 762