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/>.
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 //ASUS and TOMATO tweaks to output remaining leasetime
234 #ifdef HAVE_LEASEFILE_EXPIRE
235 ourprintf(&err
, "%u ");
238 #ifdef HAVE_BROKEN_RTC
239 ourprintf(&err
, "%u ", lease
->length
);
241 ourprintf(&err
, "%lu ", (unsigned long)lease
->expires
);
244 if (lease
->hwaddr_type
!= ARPHRD_ETHER
|| lease
->hwaddr_len
== 0)
245 ourprintf(&err
, "%.2x-", lease
->hwaddr_type
);
246 for (i
= 0; i
< lease
->hwaddr_len
; i
++)
248 ourprintf(&err
, "%.2x", lease
->hwaddr
[i
]);
249 if (i
!= lease
->hwaddr_len
- 1)
250 ourprintf(&err
, ":");
253 inet_ntop(AF_INET
, &lease
->addr
, daemon
->addrbuff
, ADDRSTRLEN
);
255 ourprintf(&err
, " %s ", daemon
->addrbuff
);
256 ourprintf(&err
, "%s ", lease
->hostname
? lease
->hostname
: "*");
258 if (lease
->clid
&& lease
->clid_len
!= 0)
260 for (i
= 0; i
< lease
->clid_len
- 1; i
++)
261 ourprintf(&err
, "%.2x:", lease
->clid
[i
]);
262 ourprintf(&err
, "%.2x\n", lease
->clid
[i
]);
265 ourprintf(&err
, "*\n");
271 ourprintf(&err
, "duid ");
272 for (i
= 0; i
< daemon
->duid_len
- 1; i
++)
273 ourprintf(&err
, "%.2x:", daemon
->duid
[i
]);
274 ourprintf(&err
, "%.2x\n", daemon
->duid
[i
]);
276 for (lease
= leases
; lease
; lease
= lease
->next
)
279 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
282 //ASUS and TOMATO tweaks to output remaining leasetime
283 #ifdef HAVE_LEASEFILE_EXPIRE
284 ourprintf(&err
, "%u ");
287 #ifdef HAVE_BROKEN_RTC
288 ourprintf(&err
, "%u ", lease
->length
);
290 ourprintf(&err
, "%lu ", (unsigned long)lease
->expires
);
293 inet_ntop(AF_INET6
, &lease
->addr6
, daemon
->addrbuff
, ADDRSTRLEN
);
295 ourprintf(&err
, "%s%u %s ", (lease
->flags
& LEASE_TA
) ? "T" : "",
296 lease
->iaid
, daemon
->addrbuff
);
297 ourprintf(&err
, "%s ", lease
->hostname
? lease
->hostname
: "*");
299 if (lease
->clid
&& lease
->clid_len
!= 0)
301 for (i
= 0; i
< lease
->clid_len
- 1; i
++)
302 ourprintf(&err
, "%.2x:", lease
->clid
[i
]);
303 ourprintf(&err
, "%.2x\n", lease
->clid
[i
]);
306 ourprintf(&err
, "*\n");
311 if (fflush(daemon
->lease_stream
) != 0 ||
312 fsync(fileno(daemon
->lease_stream
)) < 0)
319 /* Set alarm for when the first lease expires + slop. */
323 /* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
324 if (daemon
->doing_ra
)
328 if ((event
= periodic_slaac(now
, leases
)) != 0)
330 if (next_event
== 0 || difftime(next_event
, event
) > 0.0)
334 if ((event
= periodic_ra(now
)) != 0)
336 if (next_event
== 0 || difftime(next_event
, event
) > 0.0)
342 for (lease
= leases
; lease
; lease
= lease
->next
)
343 if (lease
->expires
!= 0 &&
344 (next_event
== 0 || difftime(next_event
, lease
->expires
+ 10) > 0.0))
345 next_event
= lease
->expires
+ 10;
349 if (next_event
== 0 || difftime(next_event
, LEASE_RETRY
+ now
) > 0.0)
350 next_event
= LEASE_RETRY
+ now
;
352 my_syslog(MS_DHCP
| LOG_ERR
, _("failed to write %s: %s (retry in %us)"),
353 daemon
->lease_file
, strerror(err
),
354 (unsigned int)difftime(next_event
, now
));
357 send_alarm(next_event
, now
);
361 static int find_interface_v4(struct in_addr local
, int if_index
, char *label
,
362 struct in_addr netmask
, struct in_addr broadcast
, void *vparam
)
364 struct dhcp_lease
*lease
;
370 for (lease
= leases
; lease
; lease
= lease
->next
)
371 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
372 if (is_same_net(local
, lease
->addr
, netmask
))
373 lease_set_interface(lease
, if_index
, *((time_t *)vparam
));
379 static int find_interface_v6(struct in6_addr
*local
, int prefix
,
380 int scope
, int if_index
, int flags
,
381 int preferred
, int valid
, void *vparam
)
383 struct dhcp_lease
*lease
;
390 for (lease
= leases
; lease
; lease
= lease
->next
)
391 if ((lease
->flags
& (LEASE_TA
| LEASE_NA
)))
392 if (is_same_net6(local
, &lease
->addr6
, prefix
))
393 lease_set_interface(lease
, if_index
, *((time_t *)vparam
));
398 void lease_ping_reply(struct in6_addr
*sender
, unsigned char *packet
, char *interface
)
400 /* We may be doing RA but not DHCPv4, in which case the lease
401 database may not exist and we have nothing to do anyway */
403 slaac_ping_reply(sender
, packet
, interface
, leases
);
406 void lease_update_slaac(time_t now
)
408 /* Called when we contruct a new RA-names context, to add putative
409 new SLAAC addresses to existing leases. */
411 struct dhcp_lease
*lease
;
414 for (lease
= leases
; lease
; lease
= lease
->next
)
415 slaac_add_addrs(lease
, now
, 0);
421 /* Find interfaces associated with leases at start-up. This gets updated as
422 we do DHCP transactions, but information about directly-connected subnets
423 is useful from scrips and necessary for determining SLAAC addresses from
425 void lease_find_interfaces(time_t now
)
427 iface_enumerate(AF_INET
, &now
, find_interface_v4
);
429 iface_enumerate(AF_INET6
, &now
, find_interface_v6
);
431 /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
432 if (!daemon
->duid
&& daemon
->dhcp6
)
442 void lease_update_dns(int force
)
444 struct dhcp_lease
*lease
;
446 if (daemon
->port
!= 0 && (dns_dirty
|| force
))
448 #ifndef HAVE_BROKEN_RTC
449 /* force transfer to authoritative secondaries */
455 for (lease
= leases
; lease
; lease
= lease
->next
)
460 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
462 else if (lease
->hostname
|| lease
->fqdn
)
464 struct slaac_address
*slaac
;
466 for (slaac
= lease
->slaac_address
; slaac
; slaac
= slaac
->next
)
467 if (slaac
->backoff
== 0)
470 cache_add_dhcp_entry(lease
->fqdn
, AF_INET6
, (struct all_addr
*)&slaac
->addr
, lease
->expires
);
471 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
472 cache_add_dhcp_entry(lease
->hostname
, AF_INET6
, (struct all_addr
*)&slaac
->addr
, lease
->expires
);
477 cache_add_dhcp_entry(lease
->fqdn
, prot
,
478 prot
== AF_INET
? (struct all_addr
*)&lease
->addr
: (struct all_addr
*)&lease
->addr6
,
481 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
482 cache_add_dhcp_entry(lease
->hostname
, prot
,
483 prot
== AF_INET
? (struct all_addr
*)&lease
->addr
: (struct all_addr
*)&lease
->addr6
,
488 cache_add_dhcp_entry(lease
->fqdn
, prot
, (struct all_addr
*)&lease
->addr
, lease
->expires
);
490 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
491 cache_add_dhcp_entry(lease
->hostname
, prot
, (struct all_addr
*)&lease
->addr
, lease
->expires
);
499 void lease_prune(struct dhcp_lease
*target
, time_t now
)
501 struct dhcp_lease
*lease
, *tmp
, **up
;
503 for (lease
= leases
, up
= &leases
; lease
; lease
= tmp
)
506 if ((lease
->expires
!= 0 && difftime(now
, lease
->expires
) > 0) || lease
== target
)
512 *up
= lease
->next
; /* unlink */
514 /* Put on old_leases list 'till we
515 can run the script */
516 lease
->next
= old_leases
;
527 struct dhcp_lease
*lease_find_by_client(unsigned char *hwaddr
, int hw_len
, int hw_type
,
528 unsigned char *clid
, int clid_len
)
530 struct dhcp_lease
*lease
;
533 for (lease
= leases
; lease
; lease
= lease
->next
)
536 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
539 if (lease
->clid
&& clid_len
== lease
->clid_len
&&
540 memcmp(clid
, lease
->clid
, clid_len
) == 0)
544 for (lease
= leases
; lease
; lease
= lease
->next
)
547 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
550 if ((!lease
->clid
|| !clid
) &&
552 lease
->hwaddr_len
== hw_len
&&
553 lease
->hwaddr_type
== hw_type
&&
554 memcmp(hwaddr
, lease
->hwaddr
, hw_len
) == 0)
561 struct dhcp_lease
*lease_find_by_addr(struct in_addr addr
)
563 struct dhcp_lease
*lease
;
565 for (lease
= leases
; lease
; lease
= lease
->next
)
568 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
571 if (lease
->addr
.s_addr
== addr
.s_addr
)
579 /* find address for {CLID, IAID, address} */
580 struct dhcp_lease
*lease6_find(unsigned char *clid
, int clid_len
,
581 int lease_type
, int iaid
, struct in6_addr
*addr
)
583 struct dhcp_lease
*lease
;
585 for (lease
= leases
; lease
; lease
= lease
->next
)
587 if (!(lease
->flags
& lease_type
) || lease
->iaid
!= iaid
)
590 if (!IN6_ARE_ADDR_EQUAL(&lease
->addr6
, addr
))
593 if ((clid_len
!= lease
->clid_len
||
594 memcmp(clid
, lease
->clid
, clid_len
) != 0))
603 /* reset "USED flags */
604 void lease6_reset(void)
606 struct dhcp_lease
*lease
;
608 for (lease
= leases
; lease
; lease
= lease
->next
)
609 lease
->flags
&= ~LEASE_USED
;
612 /* enumerate all leases belonging to {CLID, IAID} */
613 struct dhcp_lease
*lease6_find_by_client(struct dhcp_lease
*first
, int lease_type
, unsigned char *clid
, int clid_len
, int iaid
)
615 struct dhcp_lease
*lease
;
622 for (lease
= first
; lease
; lease
= lease
->next
)
624 if (lease
->flags
& LEASE_USED
)
627 if (!(lease
->flags
& lease_type
) || lease
->iaid
!= iaid
)
630 if ((clid_len
!= lease
->clid_len
||
631 memcmp(clid
, lease
->clid
, clid_len
) != 0))
640 struct dhcp_lease
*lease6_find_by_addr(struct in6_addr
*net
, int prefix
, u64 addr
)
642 struct dhcp_lease
*lease
;
644 for (lease
= leases
; lease
; lease
= lease
->next
)
646 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
649 if (is_same_net6(&lease
->addr6
, net
, prefix
) &&
650 (prefix
== 128 || addr6part(&lease
->addr6
) == addr
))
657 /* Find largest assigned address in context */
658 u64
lease_find_max_addr6(struct dhcp_context
*context
)
660 struct dhcp_lease
*lease
;
661 u64 addr
= addr6part(&context
->start6
);
663 if (!(context
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
)))
664 for (lease
= leases
; lease
; lease
= lease
->next
)
666 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
669 if (is_same_net6(&lease
->addr6
, &context
->start6
, 64) &&
670 addr6part(&lease
->addr6
) > addr6part(&context
->start6
) &&
671 addr6part(&lease
->addr6
) <= addr6part(&context
->end6
) &&
672 addr6part(&lease
->addr6
) > addr
)
673 addr
= addr6part(&lease
->addr6
);
681 /* Find largest assigned address in context */
682 struct in_addr
lease_find_max_addr(struct dhcp_context
*context
)
684 struct dhcp_lease
*lease
;
685 struct in_addr addr
= context
->start
;
687 if (!(context
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
)))
688 for (lease
= leases
; lease
; lease
= lease
->next
)
691 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
694 if (((unsigned)ntohl(lease
->addr
.s_addr
)) > ((unsigned)ntohl(context
->start
.s_addr
)) &&
695 ((unsigned)ntohl(lease
->addr
.s_addr
)) <= ((unsigned)ntohl(context
->end
.s_addr
)) &&
696 ((unsigned)ntohl(lease
->addr
.s_addr
)) > ((unsigned)ntohl(addr
.s_addr
)))
703 static struct dhcp_lease
*lease_allocate(void)
705 struct dhcp_lease
*lease
;
706 if (!leases_left
|| !(lease
= whine_malloc(sizeof(struct dhcp_lease
))))
709 memset(lease
, 0, sizeof(struct dhcp_lease
));
710 lease
->flags
= LEASE_NEW
;
712 #ifdef HAVE_BROKEN_RTC
713 lease
->length
= 0xffffffff; /* illegal value */
715 lease
->hwaddr_len
= 256; /* illegal value */
716 lease
->next
= leases
;
725 struct dhcp_lease
*lease4_allocate(struct in_addr addr
)
727 struct dhcp_lease
*lease
= lease_allocate();
735 struct dhcp_lease
*lease6_allocate(struct in6_addr
*addrp
, int lease_type
)
737 struct dhcp_lease
*lease
= lease_allocate();
741 lease
->addr6
= *addrp
;
742 lease
->flags
|= lease_type
;
750 void lease_set_expires(struct dhcp_lease
*lease
, unsigned int len
, time_t now
)
752 time_t exp
= now
+ (time_t)len
;
754 if (len
== 0xffffffff)
760 if (exp
!= lease
->expires
)
763 lease
->expires
= exp
;
764 #ifndef HAVE_BROKEN_RTC
765 lease
->flags
|= LEASE_AUX_CHANGED
;
770 #ifdef HAVE_BROKEN_RTC
771 if (len
!= lease
->length
)
774 lease
->flags
|= LEASE_AUX_CHANGED
;
781 void lease_set_iaid(struct dhcp_lease
*lease
, int iaid
)
783 if (lease
->iaid
!= iaid
)
786 lease
->flags
|= LEASE_CHANGED
;
791 void lease_set_hwaddr(struct dhcp_lease
*lease
, unsigned char *hwaddr
,
792 unsigned char *clid
, int hw_len
, int hw_type
, int clid_len
,
793 time_t now
, int force
)
797 lease
->flags
|= LEASE_HAVE_HWADDR
;
803 if (hw_len
!= lease
->hwaddr_len
||
804 hw_type
!= lease
->hwaddr_type
||
805 (hw_len
!= 0 && memcmp(lease
->hwaddr
, hwaddr
, hw_len
) != 0))
808 memcpy(lease
->hwaddr
, hwaddr
, hw_len
);
809 lease
->hwaddr_len
= hw_len
;
810 lease
->hwaddr_type
= hw_type
;
811 lease
->flags
|= LEASE_CHANGED
;
812 file_dirty
= 1; /* run script on change */
815 /* only update clid when one is available, stops packets
816 without a clid removing the record. Lease init uses
817 clid_len == 0 for no clid. */
818 if (clid_len
!= 0 && clid
)
823 if (lease
->clid_len
!= clid_len
)
825 lease
->flags
|= LEASE_AUX_CHANGED
;
828 if (!(lease
->clid
= whine_malloc(clid_len
)))
834 else if (memcmp(lease
->clid
, clid
, clid_len
) != 0)
836 lease
->flags
|= LEASE_AUX_CHANGED
;
843 lease
->clid_len
= clid_len
;
844 memcpy(lease
->clid
, clid
, clid_len
);
849 slaac_add_addrs(lease
, now
, force
);
853 static void kill_name(struct dhcp_lease
*lease
)
855 /* run script to say we lost our old name */
857 /* this shouldn't happen unless updates are very quick and the
858 script very slow, we just avoid a memory leak if it does. */
859 free(lease
->old_hostname
);
861 /* If we know the fqdn, pass that. The helper will derive the
862 unqualified name from it, free the unqualified name here. */
866 lease
->old_hostname
= lease
->fqdn
;
867 free(lease
->hostname
);
870 lease
->old_hostname
= lease
->hostname
;
872 lease
->hostname
= lease
->fqdn
= NULL
;
875 void lease_set_hostname(struct dhcp_lease
*lease
, char *name
, int auth
, char *domain
, char *config_domain
)
877 struct dhcp_lease
*lease_tmp
;
878 char *new_name
= NULL
, *new_fqdn
= NULL
;
880 if (config_domain
&& (!domain
|| !hostname_isequal(domain
, config_domain
)))
881 my_syslog(MS_DHCP
| LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), config_domain
, name
);
883 if (lease
->hostname
&& name
&& hostname_isequal(lease
->hostname
, name
))
886 lease
->flags
|= LEASE_AUTH_NAME
;
890 if (!name
&& !lease
->hostname
)
893 /* If a machine turns up on a new net without dropping the old lease,
894 or two machines claim the same name, then we end up with two interfaces with
895 the same name. Check for that here and remove the name from the old lease.
896 Note that IPv6 leases are different. All the leases to the same DUID are
897 allowed the same name.
899 Don't allow a name from the client to override a name from dnsmasq config. */
903 if ((new_name
= whine_malloc(strlen(name
) + 1)))
905 strcpy(new_name
, name
);
906 if (domain
&& (new_fqdn
= whine_malloc(strlen(new_name
) + strlen(domain
) + 2)))
908 strcpy(new_fqdn
, name
);
909 strcat(new_fqdn
, ".");
910 strcat(new_fqdn
, domain
);
914 /* Depending on mode, we check either unqualified name or FQDN. */
915 for (lease_tmp
= leases
; lease_tmp
; lease_tmp
= lease_tmp
->next
)
917 if (option_bool(OPT_DHCP_FQDN
))
919 if (!new_fqdn
|| !lease_tmp
->fqdn
|| !hostname_isequal(lease_tmp
->fqdn
, new_fqdn
))
924 if (!new_name
|| !lease_tmp
->hostname
|| !hostname_isequal(lease_tmp
->hostname
, new_name
) )
928 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
930 if (!(lease_tmp
->flags
& (LEASE_TA
| LEASE_NA
)))
933 /* another lease for the same DUID is OK for IPv6 */
934 if (lease
->clid_len
== lease_tmp
->clid_len
&&
935 lease
->clid
&& lease_tmp
->clid
&&
936 memcmp(lease
->clid
, lease_tmp
->clid
, lease
->clid_len
) == 0)
939 else if (lease_tmp
->flags
& (LEASE_TA
| LEASE_NA
))
942 if ((lease_tmp
->flags
& LEASE_AUTH_NAME
) && !auth
)
949 kill_name(lease_tmp
);
957 lease
->hostname
= new_name
;
958 lease
->fqdn
= new_fqdn
;
961 lease
->flags
|= LEASE_AUTH_NAME
;
965 lease
->flags
|= LEASE_CHANGED
; /* run script on change */
968 void lease_set_interface(struct dhcp_lease
*lease
, int interface
, time_t now
)
972 if (lease
->last_interface
== interface
)
975 lease
->last_interface
= interface
;
976 lease
->flags
|= LEASE_CHANGED
;
979 slaac_add_addrs(lease
, now
, 0);
983 void rerun_scripts(void)
985 struct dhcp_lease
*lease
;
987 for (lease
= leases
; lease
; lease
= lease
->next
)
988 lease
->flags
|= LEASE_CHANGED
;
991 /* deleted leases get transferred to the old_leases list.
992 remove them here, after calling the lease change
993 script. Also run the lease change script on new/modified leases.
995 Return zero if nothing to do. */
996 int do_script_run(time_t now
)
998 struct dhcp_lease
*lease
;
1003 /* If we're going to be sending DBus signals, but the connection is not yet up,
1004 delay everything until it is. */
1005 if (option_bool(OPT_DBUS
) && !daemon
->dbus
)
1013 /* If the lease still has an old_hostname, do the "old" action on that first */
1014 if (lease
->old_hostname
)
1017 queue_script(ACTION_OLD_HOSTNAME
, lease
, lease
->old_hostname
, now
);
1019 free(lease
->old_hostname
);
1020 lease
->old_hostname
= NULL
;
1026 struct slaac_address
*slaac
, *tmp
;
1027 for (slaac
= lease
->slaac_address
; slaac
; slaac
= tmp
)
1035 queue_script(ACTION_DEL
, lease
, lease
->old_hostname
, now
);
1038 emit_dbus_signal(ACTION_DEL
, lease
, lease
->old_hostname
);
1040 old_leases
= lease
->next
;
1042 free(lease
->old_hostname
);
1044 free(lease
->extradata
);
1051 /* make sure we announce the loss of a hostname before its new location. */
1052 for (lease
= leases
; lease
; lease
= lease
->next
)
1053 if (lease
->old_hostname
)
1056 queue_script(ACTION_OLD_HOSTNAME
, lease
, lease
->old_hostname
, now
);
1058 free(lease
->old_hostname
);
1059 lease
->old_hostname
= NULL
;
1063 for (lease
= leases
; lease
; lease
= lease
->next
)
1064 if ((lease
->flags
& (LEASE_NEW
| LEASE_CHANGED
)) ||
1065 ((lease
->flags
& LEASE_AUX_CHANGED
) && option_bool(OPT_LEASE_RO
)))
1068 queue_script((lease
->flags
& LEASE_NEW
) ? ACTION_ADD
: ACTION_OLD
, lease
,
1069 lease
->fqdn
? lease
->fqdn
: lease
->hostname
, now
);
1072 emit_dbus_signal((lease
->flags
& LEASE_NEW
) ? ACTION_ADD
: ACTION_OLD
, lease
,
1073 lease
->fqdn
? lease
->fqdn
: lease
->hostname
);
1075 lease
->flags
&= ~(LEASE_NEW
| LEASE_CHANGED
| LEASE_AUX_CHANGED
);
1077 /* this is used for the "add" call, then junked, since they're not in the database */
1078 free(lease
->extradata
);
1079 lease
->extradata
= NULL
;
1084 return 0; /* nothing to do */
1088 void lease_add_extradata(struct dhcp_lease
*lease
, unsigned char *data
, unsigned int len
, int delim
)
1092 /* check for embeded NULLs */
1093 for (i
= 0; i
< len
; i
++)
1100 if ((lease
->extradata_size
- lease
->extradata_len
) < (len
+ 1))
1102 size_t newsz
= lease
->extradata_len
+ len
+ 100;
1103 unsigned char *new = whine_malloc(newsz
);
1108 if (lease
->extradata
)
1110 memcpy(new, lease
->extradata
, lease
->extradata_len
);
1111 free(lease
->extradata
);
1114 lease
->extradata
= new;
1115 lease
->extradata_size
= newsz
;
1119 memcpy(lease
->extradata
+ lease
->extradata_len
, data
, len
);
1120 lease
->extradata
[lease
->extradata_len
+ len
] = delim
;
1121 lease
->extradata_len
+= len
+ 1;
1127 void tomato_helper(time_t now
)
1132 struct dhcp_lease
*lease
;
1134 // if delete exists...
1135 if ((f
= fopen("/var/tmp/dhcp/delete", "r")) != NULL
) {
1136 while (fgets(buf
, sizeof(buf
), f
)) {
1137 ia
.s_addr
= inet_addr(buf
);
1138 lease
= lease_find_by_addr(ia
);
1140 lease_prune(lease
, 0);
1141 lease_update_file(now
);
1145 unlink("/var/tmp/dhcp/delete");
1148 // dump the leases file
1149 if ((f
= fopen("/var/tmp/dhcp/leases.!", "w")) != NULL
) {
1150 for (lease
= leases
; lease
; lease
= lease
->next
) {
1151 if (lease
->hwaddr_type
== ARPHRD_ETHER
) {
1152 fprintf(f
, "%lu %02X:%02X:%02X:%02X:%02X:%02X %s %s\n",
1153 lease
->expires
- now
,
1154 lease
->hwaddr
[0], lease
->hwaddr
[1], lease
->hwaddr
[2], lease
->hwaddr
[3], lease
->hwaddr
[4], lease
->hwaddr
[5],
1155 inet_ntoa(lease
->addr
),
1156 ((lease
->hostname
) && (strlen(lease
->hostname
) > 0)) ? lease
->hostname
: "*");
1160 rename("/var/tmp/dhcp/leases.!", "/var/tmp/dhcp/leases");
1163 #endif //HAVE_TOMATO
1165 #ifdef HAVE_LEASEFILE_EXPIRE
1166 void flush_lease_file(time_t now
)
1168 static time_t flush_time
= (time_t)0;
1170 if(difftime(flush_time
, now
) < 0)
1173 lease_prune(NULL
, now
);
1174 lease_update_file(now
);
1176 if (file_dirty
== 0)
1179 #endif //HAVE_LEASEFILE_EXPIRE