Update to dnsmasq v2.66rc3
[tomato.git] / release / src / router / dnsmasq / src / lease.c
blob530571467532f864daab0b59cfeb8701c2f77b97
1 /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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.
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.
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/>.
17 #include "dnsmasq.h"
19 #ifdef HAVE_DHCP
21 static struct dhcp_lease *leases = NULL, *old_leases = NULL;
22 static int dns_dirty, file_dirty, leases_left;
24 void lease_init(time_t now)
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;
32 leases_left = daemon->dhcp_max;
34 if (option_bool(OPT_LEASE_RO))
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)
43 strcpy(daemon->dhcp_buff, daemon->lease_change_command);
44 strcat(daemon->dhcp_buff, " init");
45 leasestream = popen(daemon->dhcp_buff, "r");
47 else
48 #endif
50 file_dirty = dns_dirty = 0;
51 return;
55 else
57 /* NOTE: need a+ mode to create file if it doesn't exist */
58 leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
60 if (!leasestream)
61 die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
63 /* a+ mode leaves pointer at end. */
64 rewind(leasestream);
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)
72 #ifdef HAVE_DHCP6
73 if (strcmp(daemon->dhcp_buff3, "duid") == 0)
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;
80 #endif
82 ei = atol(daemon->dhcp_buff3);
84 if (fscanf(leasestream, " %64s %255s %764s",
85 daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
86 break;
88 clid_len = 0;
89 if (strcmp(daemon->packet, "*") != 0)
90 clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
92 if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) &&
93 (lease = lease4_allocate(addr.addr.addr4)))
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;
100 lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
101 hw_len, hw_type, clid_len, now, 0);
103 if (strcmp(daemon->dhcp_buff, "*") != 0)
104 lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
106 #ifdef HAVE_DHCP6
107 else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
109 char *s = daemon->dhcp_buff2;
110 int lease_type = LEASE_NA;
112 if (s[0] == 'T')
114 lease_type = LEASE_TA;
115 s++;
118 hw_type = atoi(s);
120 if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
122 lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, hw_type, clid_len, now, 0);
124 if (strcmp(daemon->dhcp_buff, "*") != 0)
125 lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
128 #endif
129 else
130 break;
132 if (!lease)
133 die (_("too many stored leases"), NULL, EC_MISC);
135 #ifdef HAVE_BROKEN_RTC
136 if (ei != 0)
137 lease->expires = (time_t)ei + now;
138 else
139 lease->expires = (time_t)0;
140 lease->length = ei;
141 #else
142 /* strictly time_t is opaque, but this hack should work on all sane systems,
143 even when sizeof(time_t) == 8 */
144 lease->expires = (time_t)ei;
145 #endif
147 /* set these correctly: the "old" events are generated later from
148 the startup synthesised SIGHUP. */
149 lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
152 #ifdef HAVE_SCRIPT
153 if (!daemon->lease_stream)
155 int rc = 0;
157 /* shell returns 127 for "command not found", 126 for bad permissions. */
158 if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126)
160 if (WEXITSTATUS(rc) == 127)
161 errno = ENOENT;
162 else if (WEXITSTATUS(rc) == 126)
163 errno = EACCES;
164 die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
167 if (WEXITSTATUS(rc) != 0)
169 sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
170 die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
173 #endif
175 /* Some leases may have expired */
176 file_dirty = 0;
177 lease_prune(NULL, now);
178 dns_dirty = 1;
181 void lease_update_from_configs(void)
183 /* changes to the config may change current leases. */
185 struct dhcp_lease *lease;
186 struct dhcp_config *config;
187 char *name;
189 for (lease = leases; lease; lease = lease->next)
190 if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len,
191 lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
192 (config->flags & CONFIG_NAME) &&
193 (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
194 lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
195 else if ((name = host_from_dns(lease->addr)))
196 lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
199 static void ourprintf(int *errp, char *format, ...)
201 va_list ap;
203 va_start(ap, format);
204 if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0)
205 *errp = errno;
206 va_end(ap);
209 void lease_update_file(time_t now)
211 struct dhcp_lease *lease;
212 time_t next_event;
213 int i, err = 0;
215 if (file_dirty != 0 && daemon->lease_stream)
217 errno = 0;
218 rewind(daemon->lease_stream);
219 if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0)
220 err = errno;
222 for (lease = leases; lease; lease = lease->next)
225 #ifdef HAVE_DHCP6
226 if (lease->flags & (LEASE_TA | LEASE_NA))
227 continue;
228 #endif
230 #ifdef HAVE_TOMATO
231 ourprintf(&err, "%lu ", (unsigned long)lease->expires - now);
232 #else
233 #ifdef HAVE_BROKEN_RTC
234 ourprintf(&err, "%u ", lease->length);
235 #else
236 ourprintf(&err, "%lu ", (unsigned long)lease->expires);
237 #endif
238 #endif
240 if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0)
241 ourprintf(&err, "%.2x-", lease->hwaddr_type);
242 for (i = 0; i < lease->hwaddr_len; i++)
244 ourprintf(&err, "%.2x", lease->hwaddr[i]);
245 if (i != lease->hwaddr_len - 1)
246 ourprintf(&err, ":");
249 inet_ntop(AF_INET, &lease->addr, daemon->addrbuff, ADDRSTRLEN);
251 ourprintf(&err, " %s ", daemon->addrbuff);
252 ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
254 if (lease->clid && lease->clid_len != 0)
256 for (i = 0; i < lease->clid_len - 1; i++)
257 ourprintf(&err, "%.2x:", lease->clid[i]);
258 ourprintf(&err, "%.2x\n", lease->clid[i]);
260 else
261 ourprintf(&err, "*\n");
264 #ifdef HAVE_DHCP6
265 if (daemon->duid)
267 ourprintf(&err, "duid ");
268 for (i = 0; i < daemon->duid_len - 1; i++)
269 ourprintf(&err, "%.2x:", daemon->duid[i]);
270 ourprintf(&err, "%.2x\n", daemon->duid[i]);
272 for (lease = leases; lease; lease = lease->next)
275 if (!(lease->flags & (LEASE_TA | LEASE_NA)))
276 continue;
278 #ifdef HAVE_BROKEN_RTC
279 ourprintf(&err, "%u ", lease->length);
280 #else
281 ourprintf(&err, "%lu ", (unsigned long)lease->expires);
282 #endif
284 inet_ntop(AF_INET6, lease->hwaddr, daemon->addrbuff, ADDRSTRLEN);
286 ourprintf(&err, "%s%u %s ", (lease->flags & LEASE_TA) ? "T" : "",
287 lease->hwaddr_type, daemon->addrbuff);
288 ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
290 if (lease->clid && lease->clid_len != 0)
292 for (i = 0; i < lease->clid_len - 1; i++)
293 ourprintf(&err, "%.2x:", lease->clid[i]);
294 ourprintf(&err, "%.2x\n", lease->clid[i]);
296 else
297 ourprintf(&err, "*\n");
300 #endif
302 if (fflush(daemon->lease_stream) != 0 ||
303 fsync(fileno(daemon->lease_stream)) < 0)
304 err = errno;
306 if (!err)
307 file_dirty = 0;
310 /* Set alarm for when the first lease expires + slop. */
311 next_event = 0;
313 #ifdef HAVE_DHCP6
314 /* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
315 if (daemon->doing_ra)
317 time_t event;
319 if ((event = periodic_slaac(now, leases)) != 0)
321 if (next_event == 0 || difftime(next_event, event) > 0.0)
322 next_event = event;
325 if ((event = periodic_ra(now)) != 0)
327 if (next_event == 0 || difftime(next_event, event) > 0.0)
328 next_event = event;
331 #endif
333 for (lease = leases; lease; lease = lease->next)
334 if (lease->expires != 0 &&
335 (next_event == 0 || difftime(next_event, lease->expires + 10) > 0.0))
336 next_event = lease->expires + 10;
338 if (err)
340 if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
341 next_event = LEASE_RETRY + now;
343 my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"),
344 daemon->lease_file, strerror(err),
345 (unsigned int)difftime(next_event, now));
348 send_alarm(next_event, now);
352 static int find_interface_v4(struct in_addr local, int if_index,
353 struct in_addr netmask, struct in_addr broadcast, void *vparam)
355 struct dhcp_lease *lease;
357 (void) broadcast;
358 (void) vparam;
360 for (lease = leases; lease; lease = lease->next)
361 if (!(lease->flags & (LEASE_TA | LEASE_NA)))
362 if (is_same_net(local, lease->addr, netmask))
363 lease_set_interface(lease, if_index, *((time_t *)vparam));
365 return 1;
368 #ifdef HAVE_DHCP6
369 static int find_interface_v6(struct in6_addr *local, int prefix,
370 int scope, int if_index, int flags,
371 int preferred, int valid, void *vparam)
373 struct dhcp_lease *lease;
375 (void)scope;
376 (void)flags;
377 (void)preferred;
378 (void)valid;
380 for (lease = leases; lease; lease = lease->next)
381 if ((lease->flags & (LEASE_TA | LEASE_NA)))
382 if (is_same_net6(local, (struct in6_addr *)&lease->hwaddr, prefix))
383 lease_set_interface(lease, if_index, *((time_t *)vparam));
385 return 1;
388 void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface)
390 /* We may be doing RA but not DHCPv4, in which case the lease
391 database may not exist and we have nothing to do anyway */
392 if (daemon->dhcp)
393 slaac_ping_reply(sender, packet, interface, leases);
396 void lease_update_slaac(time_t now)
398 /* Called when we contruct a new RA-names context, to add putative
399 new SLAAC addresses to existing leases. */
401 struct dhcp_lease *lease;
403 if (daemon->dhcp)
404 for (lease = leases; lease; lease = lease->next)
405 slaac_add_addrs(lease, now, 0);
408 #endif
411 /* Find interfaces associated with leases at start-up. This gets updated as
412 we do DHCP transactions, but information about directly-connected subnets
413 is useful from scrips and necessary for determining SLAAC addresses from
414 start-time. */
415 void lease_find_interfaces(time_t now)
417 iface_enumerate(AF_INET, &now, find_interface_v4);
418 #ifdef HAVE_DHCP6
419 iface_enumerate(AF_INET6, &now, find_interface_v6);
421 /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
422 if (!daemon->duid && daemon->dhcp6)
424 file_dirty = 1;
425 make_duid(now);
427 #endif
432 void lease_update_dns(int force)
434 struct dhcp_lease *lease;
436 if (daemon->port != 0 && (dns_dirty || force))
438 #ifndef HAVE_BROKEN_RTC
439 /* force transfer to authoritative secondaries */
440 daemon->soa_sn++;
441 #endif
443 cache_unhash_dhcp();
445 for (lease = leases; lease; lease = lease->next)
447 int prot = AF_INET;
449 #ifdef HAVE_DHCP6
450 if (lease->flags & (LEASE_TA | LEASE_NA))
451 prot = AF_INET6;
452 else if (lease->hostname || lease->fqdn)
454 struct slaac_address *slaac;
456 for (slaac = lease->slaac_address; slaac; slaac = slaac->next)
457 if (slaac->backoff == 0)
459 if (lease->fqdn)
460 cache_add_dhcp_entry(lease->fqdn, AF_INET6, (struct all_addr *)&slaac->addr, lease->expires);
461 if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
462 cache_add_dhcp_entry(lease->hostname, AF_INET6, (struct all_addr *)&slaac->addr, lease->expires);
465 #endif
467 if (lease->fqdn)
468 cache_add_dhcp_entry(lease->fqdn, prot,
469 prot == AF_INET ? (struct all_addr *)&lease->addr : (struct all_addr *)&lease->hwaddr,
470 lease->expires);
472 if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
473 cache_add_dhcp_entry(lease->hostname, prot,
474 prot == AF_INET ? (struct all_addr *)&lease->addr : (struct all_addr *)&lease->hwaddr,
475 lease->expires);
478 dns_dirty = 0;
482 void lease_prune(struct dhcp_lease *target, time_t now)
484 struct dhcp_lease *lease, *tmp, **up;
486 for (lease = leases, up = &leases; lease; lease = tmp)
488 tmp = lease->next;
489 if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target)
491 file_dirty = 1;
492 if (lease->hostname)
493 dns_dirty = 1;
495 *up = lease->next; /* unlink */
497 /* Put on old_leases list 'till we
498 can run the script */
499 lease->next = old_leases;
500 old_leases = lease;
502 leases_left++;
504 else
505 up = &lease->next;
510 struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
511 unsigned char *clid, int clid_len)
513 struct dhcp_lease *lease;
515 if (clid)
516 for (lease = leases; lease; lease = lease->next)
518 #ifdef HAVE_DHCP6
519 if (lease->flags & (LEASE_TA | LEASE_NA))
520 continue;
521 #endif
522 if (lease->clid && clid_len == lease->clid_len &&
523 memcmp(clid, lease->clid, clid_len) == 0)
524 return lease;
527 for (lease = leases; lease; lease = lease->next)
529 #ifdef HAVE_DHCP6
530 if (lease->flags & (LEASE_TA | LEASE_NA))
531 continue;
532 #endif
533 if ((!lease->clid || !clid) &&
534 hw_len != 0 &&
535 lease->hwaddr_len == hw_len &&
536 lease->hwaddr_type == hw_type &&
537 memcmp(hwaddr, lease->hwaddr, hw_len) == 0)
538 return lease;
541 return NULL;
544 struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
546 struct dhcp_lease *lease;
548 for (lease = leases; lease; lease = lease->next)
550 #ifdef HAVE_DHCP6
551 if (lease->flags & (LEASE_TA | LEASE_NA))
552 continue;
553 #endif
554 if (lease->addr.s_addr == addr.s_addr)
555 return lease;
558 return NULL;
561 #ifdef HAVE_DHCP6
562 /* find address for {CLID, IAID, address} */
563 struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
564 int lease_type, int iaid, struct in6_addr *addr)
566 struct dhcp_lease *lease;
568 for (lease = leases; lease; lease = lease->next)
570 if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
571 continue;
573 if (memcmp(lease->hwaddr, addr, IN6ADDRSZ) != 0)
574 continue;
576 if ((clid_len != lease->clid_len ||
577 memcmp(clid, lease->clid, clid_len) != 0))
578 continue;
580 return lease;
583 return NULL;
586 /* reset "USED flags */
587 void lease6_reset(void)
589 struct dhcp_lease *lease;
591 for (lease = leases; lease; lease = lease->next)
592 lease->flags &= ~LEASE_USED;
595 /* enumerate all leases belonging to {CLID, IAID} */
596 struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type, unsigned char *clid, int clid_len, int iaid)
598 struct dhcp_lease *lease;
600 if (!first)
601 first = leases;
603 for (lease = first; lease; lease = lease->next)
605 if (lease->flags & LEASE_USED)
606 continue;
608 if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
609 continue;
611 if ((clid_len != lease->clid_len ||
612 memcmp(clid, lease->clid, clid_len) != 0))
613 continue;
615 return lease;
618 return NULL;
621 struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
623 struct dhcp_lease *lease;
625 for (lease = leases; lease; lease = lease->next)
627 if (!(lease->flags & (LEASE_TA | LEASE_NA)))
628 continue;
630 if (is_same_net6((struct in6_addr *)lease->hwaddr, net, prefix) &&
631 (prefix == 128 || addr6part((struct in6_addr *)lease->hwaddr) == addr))
632 return lease;
635 return NULL;
638 /* Find largest assigned address in context */
639 u64 lease_find_max_addr6(struct dhcp_context *context)
641 struct dhcp_lease *lease;
642 u64 addr = addr6part(&context->start6);
644 if (!(context->flags & (CONTEXT_STATIC | CONTEXT_PROXY)))
645 for (lease = leases; lease; lease = lease->next)
647 if (!(lease->flags & (LEASE_TA | LEASE_NA)))
648 continue;
650 if (is_same_net6((struct in6_addr *)lease->hwaddr, &context->start6, 64) &&
651 addr6part((struct in6_addr *)lease->hwaddr) > addr6part(&context->start6) &&
652 addr6part((struct in6_addr *)lease->hwaddr) <= addr6part(&context->end6) &&
653 addr6part((struct in6_addr *)lease->hwaddr) > addr)
654 addr = addr6part((struct in6_addr *)lease->hwaddr);
657 return addr;
660 #endif
662 /* Find largest assigned address in context */
663 struct in_addr lease_find_max_addr(struct dhcp_context *context)
665 struct dhcp_lease *lease;
666 struct in_addr addr = context->start;
668 if (!(context->flags & (CONTEXT_STATIC | CONTEXT_PROXY)))
669 for (lease = leases; lease; lease = lease->next)
671 #ifdef HAVE_DHCP6
672 if (lease->flags & (LEASE_TA | LEASE_NA))
673 continue;
674 #endif
675 if (((unsigned)ntohl(lease->addr.s_addr)) > ((unsigned)ntohl(context->start.s_addr)) &&
676 ((unsigned)ntohl(lease->addr.s_addr)) <= ((unsigned)ntohl(context->end.s_addr)) &&
677 ((unsigned)ntohl(lease->addr.s_addr)) > ((unsigned)ntohl(addr.s_addr)))
678 addr = lease->addr;
681 return addr;
684 static struct dhcp_lease *lease_allocate(void)
686 struct dhcp_lease *lease;
687 if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease))))
688 return NULL;
690 memset(lease, 0, sizeof(struct dhcp_lease));
691 lease->flags = LEASE_NEW;
692 lease->expires = 1;
693 #ifdef HAVE_BROKEN_RTC
694 lease->length = 0xffffffff; /* illegal value */
695 #endif
696 lease->next = leases;
697 leases = lease;
699 file_dirty = 1;
700 leases_left--;
702 return lease;
705 struct dhcp_lease *lease4_allocate(struct in_addr addr)
707 struct dhcp_lease *lease = lease_allocate();
708 lease->addr = addr;
709 lease->hwaddr_len = 256; /* illegal value */
711 return lease;
714 #ifdef HAVE_DHCP6
715 struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type)
717 struct dhcp_lease *lease = lease_allocate();
718 memcpy(lease->hwaddr, addrp, sizeof(*addrp)) ;
719 lease->flags |= lease_type;
721 return lease;
723 #endif
725 void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
727 time_t exp = now + (time_t)len;
729 if (len == 0xffffffff)
731 exp = 0;
732 len = 0;
735 if (exp != lease->expires)
737 dns_dirty = 1;
738 lease->expires = exp;
739 #ifndef HAVE_BROKEN_RTC
740 lease->flags |= LEASE_AUX_CHANGED;
741 file_dirty = 1;
742 #endif
745 #ifdef HAVE_BROKEN_RTC
746 if (len != lease->length)
748 lease->length = len;
749 lease->flags |= LEASE_AUX_CHANGED;
750 file_dirty = 1;
752 #endif
755 void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
756 unsigned char *clid, int hw_len, int hw_type, int clid_len,
757 time_t now, int force)
759 #ifdef HAVE_DHCP6
760 int change = force;
761 lease->flags |= LEASE_HAVE_HWADDR;
762 #endif
764 (void)force;
766 if (hw_len != lease->hwaddr_len ||
767 hw_type != lease->hwaddr_type ||
768 (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
770 if (hw_len != 0)
771 memcpy(lease->hwaddr, hwaddr, hw_len);
772 lease->hwaddr_len = hw_len;
773 lease->hwaddr_type = hw_type;
774 lease->flags |= LEASE_CHANGED;
775 file_dirty = 1; /* run script on change */
776 #ifdef HAVE_DHCP6
777 change = 1;
778 #endif
781 /* only update clid when one is available, stops packets
782 without a clid removing the record. Lease init uses
783 clid_len == 0 for no clid. */
784 if (clid_len != 0 && clid)
786 if (!lease->clid)
787 lease->clid_len = 0;
789 if (lease->clid_len != clid_len)
791 lease->flags |= LEASE_AUX_CHANGED;
792 file_dirty = 1;
793 free(lease->clid);
794 if (!(lease->clid = whine_malloc(clid_len)))
795 return;
796 #ifdef HAVE_DHCP6
797 change = 1;
798 #endif
800 else if (memcmp(lease->clid, clid, clid_len) != 0)
802 lease->flags |= LEASE_AUX_CHANGED;
803 file_dirty = 1;
804 #ifdef HAVE_DHCP6
805 change = 1;
806 #endif
809 lease->clid_len = clid_len;
810 memcpy(lease->clid, clid, clid_len);
813 #ifdef HAVE_DHCP6
814 if (change)
815 slaac_add_addrs(lease, now, force);
816 #endif
819 static void kill_name(struct dhcp_lease *lease)
821 /* run script to say we lost our old name */
823 /* this shouldn't happen unless updates are very quick and the
824 script very slow, we just avoid a memory leak if it does. */
825 free(lease->old_hostname);
827 /* If we know the fqdn, pass that. The helper will derive the
828 unqualified name from it, free the unqualified name here. */
830 if (lease->fqdn)
832 lease->old_hostname = lease->fqdn;
833 free(lease->hostname);
835 else
836 lease->old_hostname = lease->hostname;
838 lease->hostname = lease->fqdn = NULL;
841 void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain)
843 struct dhcp_lease *lease_tmp;
844 char *new_name = NULL, *new_fqdn = NULL;
846 if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
847 my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, name);
849 if (lease->hostname && name && hostname_isequal(lease->hostname, name))
851 if (auth)
852 lease->flags |= LEASE_AUTH_NAME;
853 return;
856 if (!name && !lease->hostname)
857 return;
859 /* If a machine turns up on a new net without dropping the old lease,
860 or two machines claim the same name, then we end up with two interfaces with
861 the same name. Check for that here and remove the name from the old lease.
862 Note that IPv6 leases are different. All the leases to the same DUID are
863 allowed the same name.
865 Don't allow a name from the client to override a name from dnsmasq config. */
867 if (name)
869 if ((new_name = whine_malloc(strlen(name) + 1)))
871 strcpy(new_name, name);
872 if (domain && (new_fqdn = whine_malloc(strlen(new_name) + strlen(domain) + 2)))
874 strcpy(new_fqdn, name);
875 strcat(new_fqdn, ".");
876 strcat(new_fqdn, domain);
880 /* Depending on mode, we check either unqualified name or FQDN. */
881 for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
883 if (option_bool(OPT_DHCP_FQDN))
885 if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn))
886 continue;
888 else
890 if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) )
891 continue;
894 if (lease->flags & (LEASE_TA | LEASE_NA))
896 if (!(lease_tmp->flags & (LEASE_TA | LEASE_NA)))
897 continue;
899 /* another lease for the same DUID is OK for IPv6 */
900 if (lease->clid_len == lease_tmp->clid_len &&
901 lease->clid && lease_tmp->clid &&
902 memcmp(lease->clid, lease_tmp->clid, lease->clid_len) == 0)
903 continue;
905 else if (lease_tmp->flags & (LEASE_TA | LEASE_NA))
906 continue;
908 if ((lease_tmp->flags & LEASE_AUTH_NAME) && !auth)
910 free(new_name);
911 free(new_fqdn);
912 return;
915 kill_name(lease_tmp);
916 break;
920 if (lease->hostname)
921 kill_name(lease);
923 lease->hostname = new_name;
924 lease->fqdn = new_fqdn;
926 if (auth)
927 lease->flags |= LEASE_AUTH_NAME;
929 file_dirty = 1;
930 dns_dirty = 1;
931 lease->flags |= LEASE_CHANGED; /* run script on change */
934 void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now)
936 if (lease->last_interface == interface)
937 return;
939 lease->last_interface = interface;
940 lease->flags |= LEASE_CHANGED;
942 #ifdef HAVE_DHCP6
943 slaac_add_addrs(lease, now, 0);
944 #endif
947 void rerun_scripts(void)
949 struct dhcp_lease *lease;
951 for (lease = leases; lease; lease = lease->next)
952 lease->flags |= LEASE_CHANGED;
955 /* deleted leases get transferred to the old_leases list.
956 remove them here, after calling the lease change
957 script. Also run the lease change script on new/modified leases.
959 Return zero if nothing to do. */
960 int do_script_run(time_t now)
962 struct dhcp_lease *lease;
964 #ifdef HAVE_DBUS
965 /* If we're going to be sending DBus signals, but the connection is not yet up,
966 delay everything until it is. */
967 if (option_bool(OPT_DBUS) && !daemon->dbus)
968 return 0;
969 #endif
971 if (old_leases)
973 lease = old_leases;
975 /* If the lease still has an old_hostname, do the "old" action on that first */
976 if (lease->old_hostname)
978 #ifdef HAVE_SCRIPT
979 queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
980 #endif
981 free(lease->old_hostname);
982 lease->old_hostname = NULL;
983 return 1;
985 else
987 #ifdef HAVE_DHCP6
988 struct slaac_address *slaac, *tmp;
989 for (slaac = lease->slaac_address; slaac; slaac = tmp)
991 tmp = slaac->next;
992 free(slaac);
994 #endif
995 kill_name(lease);
996 #ifdef HAVE_SCRIPT
997 queue_script(ACTION_DEL, lease, lease->old_hostname, now);
998 #endif
999 #ifdef HAVE_DBUS
1000 emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
1001 #endif
1002 old_leases = lease->next;
1004 free(lease->old_hostname);
1005 free(lease->clid);
1006 free(lease->extradata);
1007 free(lease);
1009 return 1;
1013 /* make sure we announce the loss of a hostname before its new location. */
1014 for (lease = leases; lease; lease = lease->next)
1015 if (lease->old_hostname)
1017 #ifdef HAVE_SCRIPT
1018 queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
1019 #endif
1020 free(lease->old_hostname);
1021 lease->old_hostname = NULL;
1022 return 1;
1025 for (lease = leases; lease; lease = lease->next)
1026 if ((lease->flags & (LEASE_NEW | LEASE_CHANGED)) ||
1027 ((lease->flags & LEASE_AUX_CHANGED) && option_bool(OPT_LEASE_RO)))
1029 #ifdef HAVE_SCRIPT
1030 queue_script((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
1031 lease->fqdn ? lease->fqdn : lease->hostname, now);
1032 #endif
1033 #ifdef HAVE_DBUS
1034 emit_dbus_signal((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
1035 lease->fqdn ? lease->fqdn : lease->hostname);
1036 #endif
1037 lease->flags &= ~(LEASE_NEW | LEASE_CHANGED | LEASE_AUX_CHANGED);
1039 /* this is used for the "add" call, then junked, since they're not in the database */
1040 free(lease->extradata);
1041 lease->extradata = NULL;
1043 return 1;
1046 return 0; /* nothing to do */
1049 #ifdef HAVE_SCRIPT
1050 void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned int len, int delim)
1052 unsigned int i;
1054 /* check for embeded NULLs */
1055 for (i = 0; i < len; i++)
1056 if (data[i] == 0)
1058 len = i;
1059 break;
1062 if ((lease->extradata_size - lease->extradata_len) < (len + 1))
1064 size_t newsz = lease->extradata_len + len + 100;
1065 unsigned char *new = whine_malloc(newsz);
1067 if (!new)
1068 return;
1070 if (lease->extradata)
1072 memcpy(new, lease->extradata, lease->extradata_len);
1073 free(lease->extradata);
1076 lease->extradata = new;
1077 lease->extradata_size = newsz;
1080 if (len != 0)
1081 memcpy(lease->extradata + lease->extradata_len, data, len);
1082 lease->extradata[lease->extradata_len + len] = delim;
1083 lease->extradata_len += len + 1;
1085 #endif
1087 #ifdef HAVE_TOMATO
1089 void tomato_helper(time_t now)
1091 FILE *f;
1092 struct in_addr ia;
1093 char buf[64];
1094 struct dhcp_lease *lease;
1096 // if delete exists...
1097 if ((f = fopen("/var/tmp/dhcp/delete", "r")) != NULL) {
1098 while (fgets(buf, sizeof(buf), f)) {
1099 ia.s_addr = inet_addr(buf);
1100 lease = lease_find_by_addr(ia);
1101 if (lease) {
1102 lease_prune(lease, 0);
1103 lease_update_file(now);
1106 fclose(f);
1107 unlink("/var/tmp/dhcp/delete");
1110 // dump the leases file
1111 if ((f = fopen("/var/tmp/dhcp/leases.!", "w")) != NULL) {
1112 for (lease = leases; lease; lease = lease->next) {
1113 if (lease->hwaddr_type == ARPHRD_ETHER) {
1114 fprintf(f, "%lu %02X:%02X:%02X:%02X:%02X:%02X %s %s\n",
1115 lease->expires - now,
1116 lease->hwaddr[0], lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4], lease->hwaddr[5],
1117 inet_ntoa(lease->addr),
1118 ((lease->hostname) && (strlen(lease->hostname) > 0)) ? lease->hostname : "*");
1121 fclose(f);
1122 rename("/var/tmp/dhcp/leases.!", "/var/tmp/dhcp/leases");
1126 void flush_lease_file(time_t now)
1128 file_dirty = 1;
1129 lease_update_file(now);
1132 #endif //TOMATO
1134 #endif