]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/lease.c
545bbb7fd09c5511ac28d751a950733872beab42
[people/ms/dnsmasq.git] / src / lease.c
1 /* dnsmasq is Copyright (c) 2000-2015 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 all_addr addr;
28 struct dhcp_lease *lease;
29 int clid_len, hw_len, hw_type;
30 FILE *leasestream;
31
32 leases_left = daemon->dhcp_max;
33
34 if (option_bool(OPT_LEASE_RO))
35 {
36 /* run "<lease_change_script> init" once to get the
37 initial state of the database. If leasefile-ro is
38 set without a script, we just do without any
39 lease database. */
40 #ifdef HAVE_SCRIPT
41 if (daemon->lease_change_command)
42 {
43 strcpy(daemon->dhcp_buff, daemon->lease_change_command);
44 strcat(daemon->dhcp_buff, " init");
45 leasestream = popen(daemon->dhcp_buff, "r");
46 }
47 else
48 #endif
49 {
50 file_dirty = dns_dirty = 0;
51 return;
52 }
53
54 }
55 else
56 {
57 /* NOTE: need a+ mode to create file if it doesn't exist */
58 leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
59
60 if (!leasestream)
61 die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
62
63 /* a+ mode leaves pointer at end. */
64 rewind(leasestream);
65 }
66
67 /* client-id max length is 255 which is 255*2 digits + 254 colons
68 borrow DNS packet buffer which is always larger than 1000 bytes */
69 if (leasestream)
70 while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
71 {
72 #ifdef HAVE_DHCP6
73 if (strcmp(daemon->dhcp_buff3, "duid") == 0)
74 {
75 daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
76 daemon->duid = safe_malloc(daemon->duid_len);
77 memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
78 continue;
79 }
80 #endif
81
82 ei = atol(daemon->dhcp_buff3);
83
84 if (fscanf(leasestream, " %64s %255s %764s",
85 daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
86 break;
87
88 clid_len = 0;
89 if (strcmp(daemon->packet, "*") != 0)
90 clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
91
92 if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) &&
93 (lease = lease4_allocate(addr.addr.addr4)))
94 {
95 hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
96 /* For backwards compatibility, no explict MAC address type means ether. */
97 if (hw_type == 0 && hw_len != 0)
98 hw_type = ARPHRD_ETHER;
99
100 lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
101 hw_len, hw_type, clid_len, now, 0);
102
103 if (strcmp(daemon->dhcp_buff, "*") != 0)
104 lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
105 }
106 #ifdef HAVE_DHCP6
107 else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
108 {
109 char *s = daemon->dhcp_buff2;
110 int lease_type = LEASE_NA;
111 int iaid;
112
113 if (s[0] == 'T')
114 {
115 lease_type = LEASE_TA;
116 s++;
117 }
118
119 iaid = strtoul(s, NULL, 10);
120
121 if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
122 {
123 lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0);
124 lease_set_iaid(lease, iaid);
125 if (strcmp(daemon->dhcp_buff, "*") != 0)
126 lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
127 }
128 }
129 #endif
130 else
131 break;
132
133 if (!lease)
134 die (_("too many stored leases"), NULL, EC_MISC);
135
136 #ifdef HAVE_BROKEN_RTC
137 if (ei != 0)
138 lease->expires = (time_t)ei + now;
139 else
140 lease->expires = (time_t)0;
141 lease->length = ei;
142 #else
143 /* strictly time_t is opaque, but this hack should work on all sane systems,
144 even when sizeof(time_t) == 8 */
145 lease->expires = (time_t)ei;
146 #endif
147
148 /* set these correctly: the "old" events are generated later from
149 the startup synthesised SIGHUP. */
150 lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
151 }
152
153 #ifdef HAVE_SCRIPT
154 if (!daemon->lease_stream)
155 {
156 int rc = 0;
157
158 /* shell returns 127 for "command not found", 126 for bad permissions. */
159 if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126)
160 {
161 if (WEXITSTATUS(rc) == 127)
162 errno = ENOENT;
163 else if (WEXITSTATUS(rc) == 126)
164 errno = EACCES;
165 die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
166 }
167
168 if (WEXITSTATUS(rc) != 0)
169 {
170 sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
171 die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
172 }
173 }
174 #endif
175
176 /* Some leases may have expired */
177 file_dirty = 0;
178 lease_prune(NULL, now);
179 dns_dirty = 1;
180 }
181
182 void lease_update_from_configs(void)
183 {
184 /* changes to the config may change current leases. */
185
186 struct dhcp_lease *lease;
187 struct dhcp_config *config;
188 char *name;
189
190 for (lease = leases; lease; lease = lease->next)
191 if (lease->flags & (LEASE_TA | LEASE_NA))
192 continue;
193 else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len,
194 lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
195 (config->flags & CONFIG_NAME) &&
196 (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
197 lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
198 else if ((name = host_from_dns(lease->addr)))
199 lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
200 }
201
202 static void ourprintf(int *errp, char *format, ...)
203 {
204 va_list ap;
205
206 va_start(ap, format);
207 if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0)
208 *errp = errno;
209 va_end(ap);
210 }
211
212 void lease_update_file(time_t now)
213 {
214 struct dhcp_lease *lease;
215 time_t next_event;
216 int i, err = 0;
217
218 if (file_dirty != 0 && daemon->lease_stream)
219 {
220 errno = 0;
221 rewind(daemon->lease_stream);
222 if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0)
223 err = errno;
224
225 for (lease = leases; lease; lease = lease->next)
226 {
227
228 #ifdef HAVE_DHCP6
229 if (lease->flags & (LEASE_TA | LEASE_NA))
230 continue;
231 #endif
232
233 #ifdef HAVE_BROKEN_RTC
234 ourprintf(&err, "%u ", lease->length);
235 #else
236 ourprintf(&err, "%lu ", (unsigned long)lease->expires);
237 #endif
238
239 if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0)
240 ourprintf(&err, "%.2x-", lease->hwaddr_type);
241 for (i = 0; i < lease->hwaddr_len; i++)
242 {
243 ourprintf(&err, "%.2x", lease->hwaddr[i]);
244 if (i != lease->hwaddr_len - 1)
245 ourprintf(&err, ":");
246 }
247
248 inet_ntop(AF_INET, &lease->addr, daemon->addrbuff, ADDRSTRLEN);
249
250 ourprintf(&err, " %s ", daemon->addrbuff);
251 ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
252
253 if (lease->clid && lease->clid_len != 0)
254 {
255 for (i = 0; i < lease->clid_len - 1; i++)
256 ourprintf(&err, "%.2x:", lease->clid[i]);
257 ourprintf(&err, "%.2x\n", lease->clid[i]);
258 }
259 else
260 ourprintf(&err, "*\n");
261 }
262
263 #ifdef HAVE_DHCP6
264 if (daemon->duid)
265 {
266 ourprintf(&err, "duid ");
267 for (i = 0; i < daemon->duid_len - 1; i++)
268 ourprintf(&err, "%.2x:", daemon->duid[i]);
269 ourprintf(&err, "%.2x\n", daemon->duid[i]);
270
271 for (lease = leases; lease; lease = lease->next)
272 {
273
274 if (!(lease->flags & (LEASE_TA | LEASE_NA)))
275 continue;
276
277 #ifdef HAVE_BROKEN_RTC
278 ourprintf(&err, "%u ", lease->length);
279 #else
280 ourprintf(&err, "%lu ", (unsigned long)lease->expires);
281 #endif
282
283 inet_ntop(AF_INET6, &lease->addr6, daemon->addrbuff, ADDRSTRLEN);
284
285 ourprintf(&err, "%s%u %s ", (lease->flags & LEASE_TA) ? "T" : "",
286 lease->iaid, daemon->addrbuff);
287 ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
288
289 if (lease->clid && lease->clid_len != 0)
290 {
291 for (i = 0; i < lease->clid_len - 1; i++)
292 ourprintf(&err, "%.2x:", lease->clid[i]);
293 ourprintf(&err, "%.2x\n", lease->clid[i]);
294 }
295 else
296 ourprintf(&err, "*\n");
297 }
298 }
299 #endif
300
301 if (fflush(daemon->lease_stream) != 0 ||
302 fsync(fileno(daemon->lease_stream)) < 0)
303 err = errno;
304
305 if (!err)
306 file_dirty = 0;
307 }
308
309 /* Set alarm for when the first lease expires. */
310 next_event = 0;
311
312 #ifdef HAVE_DHCP6
313 /* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
314 if (daemon->doing_ra)
315 {
316 time_t event;
317
318 if ((event = periodic_slaac(now, leases)) != 0)
319 {
320 if (next_event == 0 || difftime(next_event, event) > 0.0)
321 next_event = event;
322 }
323
324 if ((event = periodic_ra(now)) != 0)
325 {
326 if (next_event == 0 || difftime(next_event, event) > 0.0)
327 next_event = event;
328 }
329 }
330 #endif
331
332 for (lease = leases; lease; lease = lease->next)
333 if (lease->expires != 0 &&
334 (next_event == 0 || difftime(next_event, lease->expires) > 0.0))
335 next_event = lease->expires;
336
337 if (err)
338 {
339 if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
340 next_event = LEASE_RETRY + now;
341
342 my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"),
343 daemon->lease_file, strerror(err),
344 (unsigned int)difftime(next_event, now));
345 }
346
347 send_alarm(next_event, now);
348 }
349
350
351 static int find_interface_v4(struct in_addr local, int if_index, char *label,
352 struct in_addr netmask, struct in_addr broadcast, void *vparam)
353 {
354 struct dhcp_lease *lease;
355 int prefix = netmask_length(netmask);
356
357 (void) label;
358 (void) broadcast;
359 (void) vparam;
360
361 for (lease = leases; lease; lease = lease->next)
362 if (!(lease->flags & (LEASE_TA | LEASE_NA)) &&
363 is_same_net(local, lease->addr, netmask) &&
364 prefix > lease->new_prefixlen)
365 {
366 lease->new_interface = if_index;
367 lease->new_prefixlen = prefix;
368 }
369
370 return 1;
371 }
372
373 #ifdef HAVE_DHCP6
374 static int find_interface_v6(struct in6_addr *local, int prefix,
375 int scope, int if_index, int flags,
376 int preferred, int valid, void *vparam)
377 {
378 struct dhcp_lease *lease;
379
380 (void)scope;
381 (void)flags;
382 (void)preferred;
383 (void)valid;
384 (void)vparam;
385
386 for (lease = leases; lease; lease = lease->next)
387 if ((lease->flags & (LEASE_TA | LEASE_NA)))
388 if (is_same_net6(local, &lease->addr6, prefix) && prefix > lease->new_prefixlen) {
389 /* save prefix length for comparison, as we might get shorter matching
390 * prefix in upcoming netlink GETADDR responses
391 * */
392 lease->new_interface = if_index;
393 lease->new_prefixlen = prefix;
394 }
395
396 return 1;
397 }
398
399 void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface)
400 {
401 /* We may be doing RA but not DHCPv4, in which case the lease
402 database may not exist and we have nothing to do anyway */
403 if (daemon->dhcp)
404 slaac_ping_reply(sender, packet, interface, leases);
405 }
406
407 void lease_update_slaac(time_t now)
408 {
409 /* Called when we contruct a new RA-names context, to add putative
410 new SLAAC addresses to existing leases. */
411
412 struct dhcp_lease *lease;
413
414 if (daemon->dhcp)
415 for (lease = leases; lease; lease = lease->next)
416 slaac_add_addrs(lease, now, 0);
417 }
418
419 #endif
420
421
422 /* Find interfaces associated with leases at start-up. This gets updated as
423 we do DHCP transactions, but information about directly-connected subnets
424 is useful from scrips and necessary for determining SLAAC addresses from
425 start-time. */
426 void lease_find_interfaces(time_t now)
427 {
428 struct dhcp_lease *lease;
429
430 for (lease = leases; lease; lease = lease->next)
431 lease->new_prefixlen = lease->new_interface = 0;
432
433 iface_enumerate(AF_INET, &now, find_interface_v4);
434 #ifdef HAVE_DHCP6
435 iface_enumerate(AF_INET6, &now, find_interface_v6);
436 #endif
437
438 for (lease = leases; lease; lease = lease->next)
439 if (lease->new_interface != 0)
440 lease_set_interface(lease, lease->new_interface, now);
441 }
442
443 #ifdef HAVE_DHCP6
444 void lease_make_duid(time_t now)
445 {
446 /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
447 if (!daemon->duid && daemon->doing_dhcp6)
448 {
449 file_dirty = 1;
450 make_duid(now);
451 }
452 }
453 #endif
454
455
456
457
458 void lease_update_dns(int force)
459 {
460 struct dhcp_lease *lease;
461
462 if (daemon->port != 0 && (dns_dirty || force))
463 {
464 #ifndef HAVE_BROKEN_RTC
465 /* force transfer to authoritative secondaries */
466 daemon->soa_sn++;
467 #endif
468
469 cache_unhash_dhcp();
470
471 for (lease = leases; lease; lease = lease->next)
472 {
473 int prot = AF_INET;
474
475 #ifdef HAVE_DHCP6
476 if (lease->flags & (LEASE_TA | LEASE_NA))
477 prot = AF_INET6;
478 else if (lease->hostname || lease->fqdn)
479 {
480 struct slaac_address *slaac;
481
482 for (slaac = lease->slaac_address; slaac; slaac = slaac->next)
483 if (slaac->backoff == 0)
484 {
485 if (lease->fqdn)
486 cache_add_dhcp_entry(lease->fqdn, AF_INET6, (struct all_addr *)&slaac->addr, lease->expires);
487 if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
488 cache_add_dhcp_entry(lease->hostname, AF_INET6, (struct all_addr *)&slaac->addr, lease->expires);
489 }
490 }
491
492 if (lease->fqdn)
493 cache_add_dhcp_entry(lease->fqdn, prot,
494 prot == AF_INET ? (struct all_addr *)&lease->addr : (struct all_addr *)&lease->addr6,
495 lease->expires);
496
497 if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
498 cache_add_dhcp_entry(lease->hostname, prot,
499 prot == AF_INET ? (struct all_addr *)&lease->addr : (struct all_addr *)&lease->addr6,
500 lease->expires);
501
502 #else
503 if (lease->fqdn)
504 cache_add_dhcp_entry(lease->fqdn, prot, (struct all_addr *)&lease->addr, lease->expires);
505
506 if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
507 cache_add_dhcp_entry(lease->hostname, prot, (struct all_addr *)&lease->addr, lease->expires);
508 #endif
509 }
510
511 dns_dirty = 0;
512 }
513 }
514
515 void lease_prune(struct dhcp_lease *target, time_t now)
516 {
517 struct dhcp_lease *lease, *tmp, **up;
518
519 for (lease = leases, up = &leases; lease; lease = tmp)
520 {
521 tmp = lease->next;
522 if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target)
523 {
524 file_dirty = 1;
525 if (lease->hostname)
526 dns_dirty = 1;
527
528 *up = lease->next; /* unlink */
529
530 /* Put on old_leases list 'till we
531 can run the script */
532 lease->next = old_leases;
533 old_leases = lease;
534
535 leases_left++;
536 }
537 else
538 up = &lease->next;
539 }
540 }
541
542
543 struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
544 unsigned char *clid, int clid_len)
545 {
546 struct dhcp_lease *lease;
547
548 if (clid)
549 for (lease = leases; lease; lease = lease->next)
550 {
551 #ifdef HAVE_DHCP6
552 if (lease->flags & (LEASE_TA | LEASE_NA))
553 continue;
554 #endif
555 if (lease->clid && clid_len == lease->clid_len &&
556 memcmp(clid, lease->clid, clid_len) == 0)
557 return lease;
558 }
559
560 for (lease = leases; lease; lease = lease->next)
561 {
562 #ifdef HAVE_DHCP6
563 if (lease->flags & (LEASE_TA | LEASE_NA))
564 continue;
565 #endif
566 if ((!lease->clid || !clid) &&
567 hw_len != 0 &&
568 lease->hwaddr_len == hw_len &&
569 lease->hwaddr_type == hw_type &&
570 memcmp(hwaddr, lease->hwaddr, hw_len) == 0)
571 return lease;
572 }
573
574 return NULL;
575 }
576
577 struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
578 {
579 struct dhcp_lease *lease;
580
581 for (lease = leases; lease; lease = lease->next)
582 {
583 #ifdef HAVE_DHCP6
584 if (lease->flags & (LEASE_TA | LEASE_NA))
585 continue;
586 #endif
587 if (lease->addr.s_addr == addr.s_addr)
588 return lease;
589 }
590
591 return NULL;
592 }
593
594 #ifdef HAVE_DHCP6
595 /* find address for {CLID, IAID, address} */
596 struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
597 int lease_type, int iaid, struct in6_addr *addr)
598 {
599 struct dhcp_lease *lease;
600
601 for (lease = leases; lease; lease = lease->next)
602 {
603 if (!(lease->flags & lease_type) || lease->iaid != iaid)
604 continue;
605
606 if (!IN6_ARE_ADDR_EQUAL(&lease->addr6, addr))
607 continue;
608
609 if ((clid_len != lease->clid_len ||
610 memcmp(clid, lease->clid, clid_len) != 0))
611 continue;
612
613 return lease;
614 }
615
616 return NULL;
617 }
618
619 /* reset "USED flags */
620 void lease6_reset(void)
621 {
622 struct dhcp_lease *lease;
623
624 for (lease = leases; lease; lease = lease->next)
625 lease->flags &= ~LEASE_USED;
626 }
627
628 /* enumerate all leases belonging to {CLID, IAID} */
629 struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type, unsigned char *clid, int clid_len, int iaid)
630 {
631 struct dhcp_lease *lease;
632
633 if (!first)
634 first = leases;
635 else
636 first = first->next;
637
638 for (lease = first; lease; lease = lease->next)
639 {
640 if (lease->flags & LEASE_USED)
641 continue;
642
643 if (!(lease->flags & lease_type) || lease->iaid != iaid)
644 continue;
645
646 if ((clid_len != lease->clid_len ||
647 memcmp(clid, lease->clid, clid_len) != 0))
648 continue;
649
650 return lease;
651 }
652
653 return NULL;
654 }
655
656 struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
657 {
658 struct dhcp_lease *lease;
659
660 for (lease = leases; lease; lease = lease->next)
661 {
662 if (!(lease->flags & (LEASE_TA | LEASE_NA)))
663 continue;
664
665 if (is_same_net6(&lease->addr6, net, prefix) &&
666 (prefix == 128 || addr6part(&lease->addr6) == addr))
667 return lease;
668 }
669
670 return NULL;
671 }
672
673 /* Find largest assigned address in context */
674 u64 lease_find_max_addr6(struct dhcp_context *context)
675 {
676 struct dhcp_lease *lease;
677 u64 addr = addr6part(&context->start6);
678
679 if (!(context->flags & (CONTEXT_STATIC | CONTEXT_PROXY)))
680 for (lease = leases; lease; lease = lease->next)
681 {
682 if (!(lease->flags & (LEASE_TA | LEASE_NA)))
683 continue;
684
685 if (is_same_net6(&lease->addr6, &context->start6, 64) &&
686 addr6part(&lease->addr6) > addr6part(&context->start6) &&
687 addr6part(&lease->addr6) <= addr6part(&context->end6) &&
688 addr6part(&lease->addr6) > addr)
689 addr = addr6part(&lease->addr6);
690 }
691
692 return addr;
693 }
694
695 #endif
696
697 /* Find largest assigned address in context */
698 struct in_addr lease_find_max_addr(struct dhcp_context *context)
699 {
700 struct dhcp_lease *lease;
701 struct in_addr addr = context->start;
702
703 if (!(context->flags & (CONTEXT_STATIC | CONTEXT_PROXY)))
704 for (lease = leases; lease; lease = lease->next)
705 {
706 #ifdef HAVE_DHCP6
707 if (lease->flags & (LEASE_TA | LEASE_NA))
708 continue;
709 #endif
710 if (((unsigned)ntohl(lease->addr.s_addr)) > ((unsigned)ntohl(context->start.s_addr)) &&
711 ((unsigned)ntohl(lease->addr.s_addr)) <= ((unsigned)ntohl(context->end.s_addr)) &&
712 ((unsigned)ntohl(lease->addr.s_addr)) > ((unsigned)ntohl(addr.s_addr)))
713 addr = lease->addr;
714 }
715
716 return addr;
717 }
718
719 static struct dhcp_lease *lease_allocate(void)
720 {
721 struct dhcp_lease *lease;
722 if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease))))
723 return NULL;
724
725 memset(lease, 0, sizeof(struct dhcp_lease));
726 lease->flags = LEASE_NEW;
727 lease->expires = 1;
728 #ifdef HAVE_BROKEN_RTC
729 lease->length = 0xffffffff; /* illegal value */
730 #endif
731 lease->hwaddr_len = 256; /* illegal value */
732 lease->next = leases;
733 leases = lease;
734
735 file_dirty = 1;
736 leases_left--;
737
738 return lease;
739 }
740
741 struct dhcp_lease *lease4_allocate(struct in_addr addr)
742 {
743 struct dhcp_lease *lease = lease_allocate();
744 if (lease)
745 lease->addr = addr;
746
747 return lease;
748 }
749
750 #ifdef HAVE_DHCP6
751 struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type)
752 {
753 struct dhcp_lease *lease = lease_allocate();
754
755 if (lease)
756 {
757 lease->addr6 = *addrp;
758 lease->flags |= lease_type;
759 lease->iaid = 0;
760 }
761
762 return lease;
763 }
764 #endif
765
766 void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
767 {
768 time_t exp;
769
770 if (len == 0xffffffff)
771 {
772 exp = 0;
773 len = 0;
774 }
775 else
776 {
777 exp = now + (time_t)len;
778 /* Check for 2038 overflow. Make the lease
779 inifinite in that case, as the least disruptive
780 thing we can do. */
781 if (difftime(exp, now) <= 0.0)
782 exp = 0;
783 }
784
785 if (exp != lease->expires)
786 {
787 dns_dirty = 1;
788 lease->expires = exp;
789 #ifndef HAVE_BROKEN_RTC
790 lease->flags |= LEASE_AUX_CHANGED;
791 file_dirty = 1;
792 #endif
793 }
794
795 #ifdef HAVE_BROKEN_RTC
796 if (len != lease->length)
797 {
798 lease->length = len;
799 lease->flags |= LEASE_AUX_CHANGED;
800 file_dirty = 1;
801 }
802 #endif
803 }
804
805 #ifdef HAVE_DHCP6
806 void lease_set_iaid(struct dhcp_lease *lease, int iaid)
807 {
808 if (lease->iaid != iaid)
809 {
810 lease->iaid = iaid;
811 lease->flags |= LEASE_CHANGED;
812 }
813 }
814 #endif
815
816 void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
817 unsigned char *clid, int hw_len, int hw_type, int clid_len,
818 time_t now, int force)
819 {
820 #ifdef HAVE_DHCP6
821 int change = force;
822 lease->flags |= LEASE_HAVE_HWADDR;
823 #endif
824
825 (void)force;
826 (void)now;
827
828 if (hw_len != lease->hwaddr_len ||
829 hw_type != lease->hwaddr_type ||
830 (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
831 {
832 if (hw_len != 0)
833 memcpy(lease->hwaddr, hwaddr, hw_len);
834 lease->hwaddr_len = hw_len;
835 lease->hwaddr_type = hw_type;
836 lease->flags |= LEASE_CHANGED;
837 file_dirty = 1; /* run script on change */
838 }
839
840 /* only update clid when one is available, stops packets
841 without a clid removing the record. Lease init uses
842 clid_len == 0 for no clid. */
843 if (clid_len != 0 && clid)
844 {
845 if (!lease->clid)
846 lease->clid_len = 0;
847
848 if (lease->clid_len != clid_len)
849 {
850 lease->flags |= LEASE_AUX_CHANGED;
851 file_dirty = 1;
852 free(lease->clid);
853 if (!(lease->clid = whine_malloc(clid_len)))
854 return;
855 #ifdef HAVE_DHCP6
856 change = 1;
857 #endif
858 }
859 else if (memcmp(lease->clid, clid, clid_len) != 0)
860 {
861 lease->flags |= LEASE_AUX_CHANGED;
862 file_dirty = 1;
863 #ifdef HAVE_DHCP6
864 change = 1;
865 #endif
866 }
867
868 lease->clid_len = clid_len;
869 memcpy(lease->clid, clid, clid_len);
870 }
871
872 #ifdef HAVE_DHCP6
873 if (change)
874 slaac_add_addrs(lease, now, force);
875 #endif
876 }
877
878 static void kill_name(struct dhcp_lease *lease)
879 {
880 /* run script to say we lost our old name */
881
882 /* this shouldn't happen unless updates are very quick and the
883 script very slow, we just avoid a memory leak if it does. */
884 free(lease->old_hostname);
885
886 /* If we know the fqdn, pass that. The helper will derive the
887 unqualified name from it, free the unqualified name here. */
888
889 if (lease->fqdn)
890 {
891 lease->old_hostname = lease->fqdn;
892 free(lease->hostname);
893 }
894 else
895 lease->old_hostname = lease->hostname;
896
897 lease->hostname = lease->fqdn = NULL;
898 }
899
900 void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain)
901 {
902 struct dhcp_lease *lease_tmp;
903 char *new_name = NULL, *new_fqdn = NULL;
904
905 if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
906 my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, name);
907
908 if (lease->hostname && name && hostname_isequal(lease->hostname, name))
909 {
910 if (auth)
911 lease->flags |= LEASE_AUTH_NAME;
912 return;
913 }
914
915 if (!name && !lease->hostname)
916 return;
917
918 /* If a machine turns up on a new net without dropping the old lease,
919 or two machines claim the same name, then we end up with two interfaces with
920 the same name. Check for that here and remove the name from the old lease.
921 Note that IPv6 leases are different. All the leases to the same DUID are
922 allowed the same name.
923
924 Don't allow a name from the client to override a name from dnsmasq config. */
925
926 if (name)
927 {
928 if ((new_name = whine_malloc(strlen(name) + 1)))
929 {
930 strcpy(new_name, name);
931 if (domain && (new_fqdn = whine_malloc(strlen(new_name) + strlen(domain) + 2)))
932 {
933 strcpy(new_fqdn, name);
934 strcat(new_fqdn, ".");
935 strcat(new_fqdn, domain);
936 }
937 }
938
939 /* Depending on mode, we check either unqualified name or FQDN. */
940 for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
941 {
942 if (option_bool(OPT_DHCP_FQDN))
943 {
944 if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn))
945 continue;
946 }
947 else
948 {
949 if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) )
950 continue;
951 }
952
953 if (lease->flags & (LEASE_TA | LEASE_NA))
954 {
955 if (!(lease_tmp->flags & (LEASE_TA | LEASE_NA)))
956 continue;
957
958 /* another lease for the same DUID is OK for IPv6 */
959 if (lease->clid_len == lease_tmp->clid_len &&
960 lease->clid && lease_tmp->clid &&
961 memcmp(lease->clid, lease_tmp->clid, lease->clid_len) == 0)
962 continue;
963 }
964 else if (lease_tmp->flags & (LEASE_TA | LEASE_NA))
965 continue;
966
967 if ((lease_tmp->flags & LEASE_AUTH_NAME) && !auth)
968 {
969 free(new_name);
970 free(new_fqdn);
971 return;
972 }
973
974 kill_name(lease_tmp);
975 break;
976 }
977 }
978
979 if (lease->hostname)
980 kill_name(lease);
981
982 lease->hostname = new_name;
983 lease->fqdn = new_fqdn;
984
985 if (auth)
986 lease->flags |= LEASE_AUTH_NAME;
987
988 file_dirty = 1;
989 dns_dirty = 1;
990 lease->flags |= LEASE_CHANGED; /* run script on change */
991 }
992
993 void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now)
994 {
995 (void)now;
996
997 if (lease->last_interface == interface)
998 return;
999
1000 lease->last_interface = interface;
1001 lease->flags |= LEASE_CHANGED;
1002
1003 #ifdef HAVE_DHCP6
1004 slaac_add_addrs(lease, now, 0);
1005 #endif
1006 }
1007
1008 void rerun_scripts(void)
1009 {
1010 struct dhcp_lease *lease;
1011
1012 for (lease = leases; lease; lease = lease->next)
1013 lease->flags |= LEASE_CHANGED;
1014 }
1015
1016 /* deleted leases get transferred to the old_leases list.
1017 remove them here, after calling the lease change
1018 script. Also run the lease change script on new/modified leases.
1019
1020 Return zero if nothing to do. */
1021 int do_script_run(time_t now)
1022 {
1023 struct dhcp_lease *lease;
1024
1025 (void)now;
1026
1027 #ifdef HAVE_DBUS
1028 /* If we're going to be sending DBus signals, but the connection is not yet up,
1029 delay everything until it is. */
1030 if (option_bool(OPT_DBUS) && !daemon->dbus)
1031 return 0;
1032 #endif
1033
1034 if (old_leases)
1035 {
1036 lease = old_leases;
1037
1038 /* If the lease still has an old_hostname, do the "old" action on that first */
1039 if (lease->old_hostname)
1040 {
1041 #ifdef HAVE_SCRIPT
1042 queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
1043 #endif
1044 free(lease->old_hostname);
1045 lease->old_hostname = NULL;
1046 return 1;
1047 }
1048 else
1049 {
1050 #ifdef HAVE_DHCP6
1051 struct slaac_address *slaac, *tmp;
1052 for (slaac = lease->slaac_address; slaac; slaac = tmp)
1053 {
1054 tmp = slaac->next;
1055 free(slaac);
1056 }
1057 #endif
1058 kill_name(lease);
1059 #ifdef HAVE_SCRIPT
1060 queue_script(ACTION_DEL, lease, lease->old_hostname, now);
1061 #endif
1062 #ifdef HAVE_DBUS
1063 emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
1064 #endif
1065 old_leases = lease->next;
1066
1067 free(lease->old_hostname);
1068 free(lease->clid);
1069 free(lease->extradata);
1070 free(lease);
1071
1072 return 1;
1073 }
1074 }
1075
1076 /* make sure we announce the loss of a hostname before its new location. */
1077 for (lease = leases; lease; lease = lease->next)
1078 if (lease->old_hostname)
1079 {
1080 #ifdef HAVE_SCRIPT
1081 queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
1082 #endif
1083 free(lease->old_hostname);
1084 lease->old_hostname = NULL;
1085 return 1;
1086 }
1087
1088 for (lease = leases; lease; lease = lease->next)
1089 if ((lease->flags & (LEASE_NEW | LEASE_CHANGED)) ||
1090 ((lease->flags & LEASE_AUX_CHANGED) && option_bool(OPT_LEASE_RO)))
1091 {
1092 #ifdef HAVE_SCRIPT
1093 queue_script((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
1094 lease->fqdn ? lease->fqdn : lease->hostname, now);
1095 #endif
1096 #ifdef HAVE_DBUS
1097 emit_dbus_signal((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
1098 lease->fqdn ? lease->fqdn : lease->hostname);
1099 #endif
1100 lease->flags &= ~(LEASE_NEW | LEASE_CHANGED | LEASE_AUX_CHANGED);
1101
1102 /* this is used for the "add" call, then junked, since they're not in the database */
1103 free(lease->extradata);
1104 lease->extradata = NULL;
1105
1106 return 1;
1107 }
1108
1109 return 0; /* nothing to do */
1110 }
1111
1112 #ifdef HAVE_SCRIPT
1113 void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned int len, int delim)
1114 {
1115 unsigned int i;
1116
1117 /* check for embeded NULLs */
1118 for (i = 0; i < len; i++)
1119 if (data[i] == 0)
1120 {
1121 len = i;
1122 break;
1123 }
1124
1125 if ((lease->extradata_size - lease->extradata_len) < (len + 1))
1126 {
1127 size_t newsz = lease->extradata_len + len + 100;
1128 unsigned char *new = whine_malloc(newsz);
1129
1130 if (!new)
1131 return;
1132
1133 if (lease->extradata)
1134 {
1135 memcpy(new, lease->extradata, lease->extradata_len);
1136 free(lease->extradata);
1137 }
1138
1139 lease->extradata = new;
1140 lease->extradata_size = newsz;
1141 }
1142
1143 if (len != 0)
1144 memcpy(lease->extradata + lease->extradata_len, data, len);
1145 lease->extradata[lease->extradata_len + len] = delim;
1146 lease->extradata_len += len + 1;
1147 }
1148 #endif
1149
1150 #endif
1151
1152
1153
1154