]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/lease.c
1 /* dnsmasq is Copyright (c) 2000-2015 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/>.
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
)
28 struct dhcp_lease
*lease
;
29 int clid_len
, hw_len
, hw_type
;
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
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");
50 file_dirty
= dns_dirty
= 0;
57 /* NOTE: need a+ mode to create file if it doesn't exist */
58 leasestream
= daemon
->lease_stream
= fopen(daemon
->lease_file
, "a+");
61 die(_("cannot open or create lease file %s: %s"), daemon
->lease_file
, EC_FILE
);
63 /* a+ mode leaves pointer at end. */
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 */
70 while (fscanf(leasestream
, "%255s %255s", daemon
->dhcp_buff3
, daemon
->dhcp_buff2
) == 2)
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
);
82 ei
= atol(daemon
->dhcp_buff3
);
84 if (fscanf(leasestream
, " %64s %255s %764s",
85 daemon
->namebuff
, daemon
->dhcp_buff
, daemon
->packet
) != 3)
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
);
107 else if (inet_pton(AF_INET6
, daemon
->namebuff
, &addr
.addr
.addr6
))
109 char *s
= daemon
->dhcp_buff2
;
110 int lease_type
= LEASE_NA
;
115 lease_type
= LEASE_TA
;
119 iaid
= strtoul(s
, NULL
, 10);
121 if ((lease
= lease6_allocate(&addr
.addr
.addr6
, lease_type
)))
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
);
134 die (_("too many stored leases"), NULL
, EC_MISC
);
136 #ifdef HAVE_BROKEN_RTC
138 lease
->expires
= (time_t)ei
+ now
;
140 lease
->expires
= (time_t)0;
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
;
148 /* set these correctly: the "old" events are generated later from
149 the startup synthesised SIGHUP. */
150 lease
->flags
&= ~(LEASE_NEW
| LEASE_CHANGED
);
154 if (!daemon
->lease_stream
)
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)
161 if (WEXITSTATUS(rc
) == 127)
163 else if (WEXITSTATUS(rc
) == 126)
165 die(_("cannot run lease-init script %s: %s"), daemon
->lease_change_command
, EC_FILE
);
168 if (WEXITSTATUS(rc
) != 0)
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
);
176 /* Some leases may have expired */
178 lease_prune(NULL
, now
);
182 void lease_update_from_configs(void)
184 /* changes to the config may change current leases. */
186 struct dhcp_lease
*lease
;
187 struct dhcp_config
*config
;
190 for (lease
= leases
; lease
; lease
= lease
->next
)
191 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
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 */
202 static void ourprintf(int *errp
, char *format
, ...)
206 va_start(ap
, format
);
207 if (!(*errp
) && vfprintf(daemon
->lease_stream
, format
, ap
) < 0)
212 void lease_update_file(time_t now
)
214 struct dhcp_lease
*lease
;
218 if (file_dirty
!= 0 && daemon
->lease_stream
)
221 rewind(daemon
->lease_stream
);
222 if (errno
!= 0 || ftruncate(fileno(daemon
->lease_stream
), 0) != 0)
225 for (lease
= leases
; lease
; lease
= lease
->next
)
229 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
233 #ifdef HAVE_BROKEN_RTC
234 ourprintf(&err
, "%u ", lease
->length
);
236 ourprintf(&err
, "%lu ", (unsigned long)lease
->expires
);
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
++)
243 ourprintf(&err
, "%.2x", lease
->hwaddr
[i
]);
244 if (i
!= lease
->hwaddr_len
- 1)
245 ourprintf(&err
, ":");
248 inet_ntop(AF_INET
, &lease
->addr
, daemon
->addrbuff
, ADDRSTRLEN
);
250 ourprintf(&err
, " %s ", daemon
->addrbuff
);
251 ourprintf(&err
, "%s ", lease
->hostname
? lease
->hostname
: "*");
253 if (lease
->clid
&& lease
->clid_len
!= 0)
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
]);
260 ourprintf(&err
, "*\n");
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
]);
271 for (lease
= leases
; lease
; lease
= lease
->next
)
274 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
277 #ifdef HAVE_BROKEN_RTC
278 ourprintf(&err
, "%u ", lease
->length
);
280 ourprintf(&err
, "%lu ", (unsigned long)lease
->expires
);
283 inet_ntop(AF_INET6
, &lease
->addr6
, daemon
->addrbuff
, ADDRSTRLEN
);
285 ourprintf(&err
, "%s%u %s ", (lease
->flags
& LEASE_TA
) ? "T" : "",
286 lease
->iaid
, daemon
->addrbuff
);
287 ourprintf(&err
, "%s ", lease
->hostname
? lease
->hostname
: "*");
289 if (lease
->clid
&& lease
->clid_len
!= 0)
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
]);
296 ourprintf(&err
, "*\n");
301 if (fflush(daemon
->lease_stream
) != 0 ||
302 fsync(fileno(daemon
->lease_stream
)) < 0)
309 /* Set alarm for when the first lease expires. */
313 /* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
314 if (daemon
->doing_ra
)
318 if ((event
= periodic_slaac(now
, leases
)) != 0)
320 if (next_event
== 0 || difftime(next_event
, event
) > 0.0)
324 if ((event
= periodic_ra(now
)) != 0)
326 if (next_event
== 0 || difftime(next_event
, event
) > 0.0)
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
;
339 if (next_event
== 0 || difftime(next_event
, LEASE_RETRY
+ now
) > 0.0)
340 next_event
= LEASE_RETRY
+ now
;
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
));
347 send_alarm(next_event
, now
);
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
)
354 struct dhcp_lease
*lease
;
355 int prefix
= netmask_length(netmask
);
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
)
366 lease
->new_interface
= if_index
;
367 lease
->new_prefixlen
= prefix
;
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
)
378 struct dhcp_lease
*lease
;
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
392 lease
->new_interface
= if_index
;
393 lease
->new_prefixlen
= prefix
;
399 void lease_ping_reply(struct in6_addr
*sender
, unsigned char *packet
, char *interface
)
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 */
404 slaac_ping_reply(sender
, packet
, interface
, leases
);
407 void lease_update_slaac(time_t now
)
409 /* Called when we contruct a new RA-names context, to add putative
410 new SLAAC addresses to existing leases. */
412 struct dhcp_lease
*lease
;
415 for (lease
= leases
; lease
; lease
= lease
->next
)
416 slaac_add_addrs(lease
, now
, 0);
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
426 void lease_find_interfaces(time_t now
)
428 struct dhcp_lease
*lease
;
430 for (lease
= leases
; lease
; lease
= lease
->next
)
431 lease
->new_prefixlen
= lease
->new_interface
= 0;
433 iface_enumerate(AF_INET
, &now
, find_interface_v4
);
435 iface_enumerate(AF_INET6
, &now
, find_interface_v6
);
438 for (lease
= leases
; lease
; lease
= lease
->next
)
439 if (lease
->new_interface
!= 0)
440 lease_set_interface(lease
, lease
->new_interface
, now
);
444 void lease_make_duid(time_t now
)
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
)
458 void lease_update_dns(int force
)
460 struct dhcp_lease
*lease
;
462 if (daemon
->port
!= 0 && (dns_dirty
|| force
))
464 #ifndef HAVE_BROKEN_RTC
465 /* force transfer to authoritative secondaries */
471 for (lease
= leases
; lease
; lease
= lease
->next
)
476 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
478 else if (lease
->hostname
|| lease
->fqdn
)
480 struct slaac_address
*slaac
;
482 for (slaac
= lease
->slaac_address
; slaac
; slaac
= slaac
->next
)
483 if (slaac
->backoff
== 0)
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
);
493 cache_add_dhcp_entry(lease
->fqdn
, prot
,
494 prot
== AF_INET
? (struct all_addr
*)&lease
->addr
: (struct all_addr
*)&lease
->addr6
,
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
,
504 cache_add_dhcp_entry(lease
->fqdn
, prot
, (struct all_addr
*)&lease
->addr
, lease
->expires
);
506 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
507 cache_add_dhcp_entry(lease
->hostname
, prot
, (struct all_addr
*)&lease
->addr
, lease
->expires
);
515 void lease_prune(struct dhcp_lease
*target
, time_t now
)
517 struct dhcp_lease
*lease
, *tmp
, **up
;
519 for (lease
= leases
, up
= &leases
; lease
; lease
= tmp
)
522 if ((lease
->expires
!= 0 && difftime(now
, lease
->expires
) > 0) || lease
== target
)
528 *up
= lease
->next
; /* unlink */
530 /* Put on old_leases list 'till we
531 can run the script */
532 lease
->next
= old_leases
;
543 struct dhcp_lease
*lease_find_by_client(unsigned char *hwaddr
, int hw_len
, int hw_type
,
544 unsigned char *clid
, int clid_len
)
546 struct dhcp_lease
*lease
;
549 for (lease
= leases
; lease
; lease
= lease
->next
)
552 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
555 if (lease
->clid
&& clid_len
== lease
->clid_len
&&
556 memcmp(clid
, lease
->clid
, clid_len
) == 0)
560 for (lease
= leases
; lease
; lease
= lease
->next
)
563 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
566 if ((!lease
->clid
|| !clid
) &&
568 lease
->hwaddr_len
== hw_len
&&
569 lease
->hwaddr_type
== hw_type
&&
570 memcmp(hwaddr
, lease
->hwaddr
, hw_len
) == 0)
577 struct dhcp_lease
*lease_find_by_addr(struct in_addr addr
)
579 struct dhcp_lease
*lease
;
581 for (lease
= leases
; lease
; lease
= lease
->next
)
584 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
587 if (lease
->addr
.s_addr
== addr
.s_addr
)
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
)
599 struct dhcp_lease
*lease
;
601 for (lease
= leases
; lease
; lease
= lease
->next
)
603 if (!(lease
->flags
& lease_type
) || lease
->iaid
!= iaid
)
606 if (!IN6_ARE_ADDR_EQUAL(&lease
->addr6
, addr
))
609 if ((clid_len
!= lease
->clid_len
||
610 memcmp(clid
, lease
->clid
, clid_len
) != 0))
619 /* reset "USED flags */
620 void lease6_reset(void)
622 struct dhcp_lease
*lease
;
624 for (lease
= leases
; lease
; lease
= lease
->next
)
625 lease
->flags
&= ~LEASE_USED
;
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
)
631 struct dhcp_lease
*lease
;
638 for (lease
= first
; lease
; lease
= lease
->next
)
640 if (lease
->flags
& LEASE_USED
)
643 if (!(lease
->flags
& lease_type
) || lease
->iaid
!= iaid
)
646 if ((clid_len
!= lease
->clid_len
||
647 memcmp(clid
, lease
->clid
, clid_len
) != 0))
656 struct dhcp_lease
*lease6_find_by_addr(struct in6_addr
*net
, int prefix
, u64 addr
)
658 struct dhcp_lease
*lease
;
660 for (lease
= leases
; lease
; lease
= lease
->next
)
662 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
665 if (is_same_net6(&lease
->addr6
, net
, prefix
) &&
666 (prefix
== 128 || addr6part(&lease
->addr6
) == addr
))
673 /* Find largest assigned address in context */
674 u64
lease_find_max_addr6(struct dhcp_context
*context
)
676 struct dhcp_lease
*lease
;
677 u64 addr
= addr6part(&context
->start6
);
679 if (!(context
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
)))
680 for (lease
= leases
; lease
; lease
= lease
->next
)
682 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
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
);
697 /* Find largest assigned address in context */
698 struct in_addr
lease_find_max_addr(struct dhcp_context
*context
)
700 struct dhcp_lease
*lease
;
701 struct in_addr addr
= context
->start
;
703 if (!(context
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
)))
704 for (lease
= leases
; lease
; lease
= lease
->next
)
707 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
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
)))
719 static struct dhcp_lease
*lease_allocate(void)
721 struct dhcp_lease
*lease
;
722 if (!leases_left
|| !(lease
= whine_malloc(sizeof(struct dhcp_lease
))))
725 memset(lease
, 0, sizeof(struct dhcp_lease
));
726 lease
->flags
= LEASE_NEW
;
728 #ifdef HAVE_BROKEN_RTC
729 lease
->length
= 0xffffffff; /* illegal value */
731 lease
->hwaddr_len
= 256; /* illegal value */
732 lease
->next
= leases
;
741 struct dhcp_lease
*lease4_allocate(struct in_addr addr
)
743 struct dhcp_lease
*lease
= lease_allocate();
751 struct dhcp_lease
*lease6_allocate(struct in6_addr
*addrp
, int lease_type
)
753 struct dhcp_lease
*lease
= lease_allocate();
757 lease
->addr6
= *addrp
;
758 lease
->flags
|= lease_type
;
766 void lease_set_expires(struct dhcp_lease
*lease
, unsigned int len
, time_t now
)
770 if (len
== 0xffffffff)
777 exp
= now
+ (time_t)len
;
778 /* Check for 2038 overflow. Make the lease
779 inifinite in that case, as the least disruptive
781 if (difftime(exp
, now
) <= 0.0)
785 if (exp
!= lease
->expires
)
788 lease
->expires
= exp
;
789 #ifndef HAVE_BROKEN_RTC
790 lease
->flags
|= LEASE_AUX_CHANGED
;
795 #ifdef HAVE_BROKEN_RTC
796 if (len
!= lease
->length
)
799 lease
->flags
|= LEASE_AUX_CHANGED
;
806 void lease_set_iaid(struct dhcp_lease
*lease
, int iaid
)
808 if (lease
->iaid
!= iaid
)
811 lease
->flags
|= LEASE_CHANGED
;
816 void lease_set_hwaddr(struct dhcp_lease
*lease
, const unsigned char *hwaddr
,
817 const unsigned char *clid
, int hw_len
, int hw_type
,
818 int clid_len
, time_t now
, int force
)
822 lease
->flags
|= LEASE_HAVE_HWADDR
;
828 if (hw_len
!= lease
->hwaddr_len
||
829 hw_type
!= lease
->hwaddr_type
||
830 (hw_len
!= 0 && memcmp(lease
->hwaddr
, hwaddr
, 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 */
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
)
848 if (lease
->clid_len
!= clid_len
)
850 lease
->flags
|= LEASE_AUX_CHANGED
;
853 if (!(lease
->clid
= whine_malloc(clid_len
)))
859 else if (memcmp(lease
->clid
, clid
, clid_len
) != 0)
861 lease
->flags
|= LEASE_AUX_CHANGED
;
868 lease
->clid_len
= clid_len
;
869 memcpy(lease
->clid
, clid
, clid_len
);
874 slaac_add_addrs(lease
, now
, force
);
878 static void kill_name(struct dhcp_lease
*lease
)
880 /* run script to say we lost our old name */
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
);
886 /* If we know the fqdn, pass that. The helper will derive the
887 unqualified name from it, free the unqualified name here. */
891 lease
->old_hostname
= lease
->fqdn
;
892 free(lease
->hostname
);
895 lease
->old_hostname
= lease
->hostname
;
897 lease
->hostname
= lease
->fqdn
= NULL
;
900 void lease_set_hostname(struct dhcp_lease
*lease
, const char *name
, int auth
, char *domain
, char *config_domain
)
902 struct dhcp_lease
*lease_tmp
;
903 char *new_name
= NULL
, *new_fqdn
= NULL
;
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
);
908 if (lease
->hostname
&& name
&& hostname_isequal(lease
->hostname
, name
))
911 lease
->flags
|= LEASE_AUTH_NAME
;
915 if (!name
&& !lease
->hostname
)
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.
924 Don't allow a name from the client to override a name from dnsmasq config. */
928 if ((new_name
= whine_malloc(strlen(name
) + 1)))
930 strcpy(new_name
, name
);
931 if (domain
&& (new_fqdn
= whine_malloc(strlen(new_name
) + strlen(domain
) + 2)))
933 strcpy(new_fqdn
, name
);
934 strcat(new_fqdn
, ".");
935 strcat(new_fqdn
, domain
);
939 /* Depending on mode, we check either unqualified name or FQDN. */
940 for (lease_tmp
= leases
; lease_tmp
; lease_tmp
= lease_tmp
->next
)
942 if (option_bool(OPT_DHCP_FQDN
))
944 if (!new_fqdn
|| !lease_tmp
->fqdn
|| !hostname_isequal(lease_tmp
->fqdn
, new_fqdn
))
949 if (!new_name
|| !lease_tmp
->hostname
|| !hostname_isequal(lease_tmp
->hostname
, new_name
) )
953 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
955 if (!(lease_tmp
->flags
& (LEASE_TA
| LEASE_NA
)))
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)
964 else if (lease_tmp
->flags
& (LEASE_TA
| LEASE_NA
))
967 if ((lease_tmp
->flags
& LEASE_AUTH_NAME
) && !auth
)
974 kill_name(lease_tmp
);
982 lease
->hostname
= new_name
;
983 lease
->fqdn
= new_fqdn
;
986 lease
->flags
|= LEASE_AUTH_NAME
;
990 lease
->flags
|= LEASE_CHANGED
; /* run script on change */
993 void lease_set_interface(struct dhcp_lease
*lease
, int interface
, time_t now
)
997 if (lease
->last_interface
== interface
)
1000 lease
->last_interface
= interface
;
1001 lease
->flags
|= LEASE_CHANGED
;
1004 slaac_add_addrs(lease
, now
, 0);
1008 void rerun_scripts(void)
1010 struct dhcp_lease
*lease
;
1012 for (lease
= leases
; lease
; lease
= lease
->next
)
1013 lease
->flags
|= LEASE_CHANGED
;
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.
1020 Return zero if nothing to do. */
1021 int do_script_run(time_t now
)
1023 struct dhcp_lease
*lease
;
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
)
1038 /* If the lease still has an old_hostname, do the "old" action on that first */
1039 if (lease
->old_hostname
)
1042 queue_script(ACTION_OLD_HOSTNAME
, lease
, lease
->old_hostname
, now
);
1044 free(lease
->old_hostname
);
1045 lease
->old_hostname
= NULL
;
1051 struct slaac_address
*slaac
, *tmp
;
1052 for (slaac
= lease
->slaac_address
; slaac
; slaac
= tmp
)
1060 queue_script(ACTION_DEL
, lease
, lease
->old_hostname
, now
);
1063 emit_dbus_signal(ACTION_DEL
, lease
, lease
->old_hostname
);
1065 old_leases
= lease
->next
;
1067 free(lease
->old_hostname
);
1069 free(lease
->extradata
);
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
)
1081 queue_script(ACTION_OLD_HOSTNAME
, lease
, lease
->old_hostname
, now
);
1083 free(lease
->old_hostname
);
1084 lease
->old_hostname
= NULL
;
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
)))
1093 queue_script((lease
->flags
& LEASE_NEW
) ? ACTION_ADD
: ACTION_OLD
, lease
,
1094 lease
->fqdn
? lease
->fqdn
: lease
->hostname
, now
);
1097 emit_dbus_signal((lease
->flags
& LEASE_NEW
) ? ACTION_ADD
: ACTION_OLD
, lease
,
1098 lease
->fqdn
? lease
->fqdn
: lease
->hostname
);
1100 lease
->flags
&= ~(LEASE_NEW
| LEASE_CHANGED
| LEASE_AUX_CHANGED
);
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
;
1109 return 0; /* nothing to do */
1113 void lease_add_extradata(struct dhcp_lease
*lease
, unsigned char *data
, unsigned int len
, int delim
)
1117 /* check for embeded NULLs */
1118 for (i
= 0; i
< len
; i
++)
1125 if ((lease
->extradata_size
- lease
->extradata_len
) < (len
+ 1))
1127 size_t newsz
= lease
->extradata_len
+ len
+ 100;
1128 unsigned char *new = whine_malloc(newsz
);
1133 if (lease
->extradata
)
1135 memcpy(new, lease
->extradata
, lease
->extradata_len
);
1136 free(lease
->extradata
);
1139 lease
->extradata
= new;
1140 lease
->extradata_size
= newsz
;
1144 memcpy(lease
->extradata
+ lease
->extradata_len
, data
, len
);
1145 lease
->extradata
[lease
->extradata_len
+ len
] = delim
;
1146 lease
->extradata_len
+= len
+ 1;