1 /* dnsmasq is Copyright (c) 2000-2014 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 //Some ASUS & TOMATO tweaks
137 #if defined(HAVE_BROKEN_RTC) || defined(HAVE_LEASEFILE_EXPIRE)
139 lease
->expires
= (time_t)ei
+ now
;
141 lease
->expires
= (time_t)0;
142 #ifdef HAVE_BROKEN_RTC
146 /* strictly time_t is opaque, but this hack should work on all sane
147 systems, even when sizeof(time_t) == 8 */
148 lease
->expires
= (time_t)ei
;
151 /* set these correctly: the "old" events are generated later from
152 the startup synthesised SIGHUP. */
153 lease
->flags
&= ~(LEASE_NEW
| LEASE_CHANGED
);
157 if (!daemon
->lease_stream
)
161 /* shell returns 127 for "command not found", 126 for bad permissions. */
162 if (!leasestream
|| (rc
= pclose(leasestream
)) == -1 || WEXITSTATUS(rc
) == 127 || WEXITSTATUS(rc
) == 126)
164 if (WEXITSTATUS(rc
) == 127)
166 else if (WEXITSTATUS(rc
) == 126)
168 die(_("cannot run lease-init script %s: %s"), daemon
->lease_change_command
, EC_FILE
);
171 if (WEXITSTATUS(rc
) != 0)
173 sprintf(daemon
->dhcp_buff
, "%d", WEXITSTATUS(rc
));
174 die(_("lease-init script returned exit code %s"), daemon
->dhcp_buff
, WEXITSTATUS(rc
) + EC_INIT_OFFSET
);
179 /* Some leases may have expired */
181 lease_prune(NULL
, now
);
185 void lease_update_from_configs(void)
187 /* changes to the config may change current leases. */
189 struct dhcp_lease
*lease
;
190 struct dhcp_config
*config
;
193 for (lease
= leases
; lease
; lease
= lease
->next
)
194 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
196 else if ((config
= find_config(daemon
->dhcp_conf
, NULL
, lease
->clid
, lease
->clid_len
,
197 lease
->hwaddr
, lease
->hwaddr_len
, lease
->hwaddr_type
, NULL
)) &&
198 (config
->flags
& CONFIG_NAME
) &&
199 (!(config
->flags
& CONFIG_ADDR
) || config
->addr
.s_addr
== lease
->addr
.s_addr
))
200 lease_set_hostname(lease
, config
->hostname
, 1, get_domain(lease
->addr
), NULL
);
201 else if ((name
= host_from_dns(lease
->addr
)))
202 lease_set_hostname(lease
, name
, 1, get_domain(lease
->addr
), NULL
); /* updates auth flag only */
205 static void ourprintf(int *errp
, char *format
, ...)
209 va_start(ap
, format
);
210 if (!(*errp
) && vfprintf(daemon
->lease_stream
, format
, ap
) < 0)
215 void lease_update_file(time_t now
)
217 struct dhcp_lease
*lease
;
221 if (file_dirty
!= 0 && daemon
->lease_stream
)
224 rewind(daemon
->lease_stream
);
225 if (errno
!= 0 || ftruncate(fileno(daemon
->lease_stream
), 0) != 0)
228 for (lease
= leases
; lease
; lease
= lease
->next
)
232 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
236 //ASUS and TOMATO tweaks to output remaining leasetime
237 #ifdef HAVE_LEASEFILE_EXPIRE
238 ourprintf(&err
, "%u ",
239 #ifdef HAVE_BROKEN_RTC
240 (lease
->length
== 0) ? 0 :
242 (lease
->expires
== 0) ? 0 :
244 (unsigned int)difftime(lease
->expires
, now
));
245 #elif defined(HAVE_BROKEN_RTC)
246 ourprintf(&err
, "%u ", lease
->length
);
248 ourprintf(&err
, "%lu ", (unsigned long)lease
->expires
);
251 if (lease
->hwaddr_type
!= ARPHRD_ETHER
|| lease
->hwaddr_len
== 0)
252 ourprintf(&err
, "%.2x-", lease
->hwaddr_type
);
253 for (i
= 0; i
< lease
->hwaddr_len
; i
++)
255 ourprintf(&err
, "%.2x", lease
->hwaddr
[i
]);
256 if (i
!= lease
->hwaddr_len
- 1)
257 ourprintf(&err
, ":");
260 inet_ntop(AF_INET
, &lease
->addr
, daemon
->addrbuff
, ADDRSTRLEN
);
262 ourprintf(&err
, " %s ", daemon
->addrbuff
);
263 ourprintf(&err
, "%s ", lease
->hostname
? lease
->hostname
: "*");
265 if (lease
->clid
&& lease
->clid_len
!= 0)
267 for (i
= 0; i
< lease
->clid_len
- 1; i
++)
268 ourprintf(&err
, "%.2x:", lease
->clid
[i
]);
269 ourprintf(&err
, "%.2x\n", lease
->clid
[i
]);
272 ourprintf(&err
, "*\n");
278 ourprintf(&err
, "duid ");
279 for (i
= 0; i
< daemon
->duid_len
- 1; i
++)
280 ourprintf(&err
, "%.2x:", daemon
->duid
[i
]);
281 ourprintf(&err
, "%.2x\n", daemon
->duid
[i
]);
283 for (lease
= leases
; lease
; lease
= lease
->next
)
286 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
289 //ASUS and TOMATO tweaks to output remaining leasetime
290 #ifdef HAVE_LEASEFILE_EXPIRE
291 ourprintf(&err
, "%u ",
292 #ifdef HAVE_BROKEN_RTC
293 (lease
->length
== 0) ? 0 :
295 (lease
->expires
== 0) ? 0 :
297 (unsigned int)difftime(lease
->expires
, now
));
298 #elif defined(HAVE_BROKEN_RTC)
299 ourprintf(&err
, "%u ", lease
->length
);
301 ourprintf(&err
, "%lu ", (unsigned long)lease
->expires
);
304 inet_ntop(AF_INET6
, &lease
->addr6
, daemon
->addrbuff
, ADDRSTRLEN
);
306 ourprintf(&err
, "%s%u %s ", (lease
->flags
& LEASE_TA
) ? "T" : "",
307 lease
->iaid
, daemon
->addrbuff
);
308 ourprintf(&err
, "%s ", lease
->hostname
? lease
->hostname
: "*");
310 if (lease
->clid
&& lease
->clid_len
!= 0)
312 for (i
= 0; i
< lease
->clid_len
- 1; i
++)
313 ourprintf(&err
, "%.2x:", lease
->clid
[i
]);
314 ourprintf(&err
, "%.2x\n", lease
->clid
[i
]);
317 ourprintf(&err
, "*\n");
322 if (fflush(daemon
->lease_stream
) != 0 ||
323 fsync(fileno(daemon
->lease_stream
)) < 0)
330 /* Set alarm for when the first lease expires. */
334 /* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
335 if (daemon
->doing_ra
)
339 if ((event
= periodic_slaac(now
, leases
)) != 0)
341 if (next_event
== 0 || difftime(next_event
, event
) > 0.0)
345 if ((event
= periodic_ra(now
)) != 0)
347 if (next_event
== 0 || difftime(next_event
, event
) > 0.0)
353 for (lease
= leases
; lease
; lease
= lease
->next
)
354 if (lease
->expires
!= 0 &&
355 (next_event
== 0 || difftime(next_event
, lease
->expires
) > 0.0))
356 next_event
= lease
->expires
;
360 if (next_event
== 0 || difftime(next_event
, LEASE_RETRY
+ now
) > 0.0)
361 next_event
= LEASE_RETRY
+ now
;
363 my_syslog(MS_DHCP
| LOG_ERR
, _("failed to write %s: %s (retry in %us)"),
364 daemon
->lease_file
, strerror(err
),
365 (unsigned int)difftime(next_event
, now
));
368 send_alarm(next_event
, now
);
372 static int find_interface_v4(struct in_addr local
, int if_index
, char *label
,
373 struct in_addr netmask
, struct in_addr broadcast
, void *vparam
)
375 struct dhcp_lease
*lease
;
376 int prefix
= netmask_length(netmask
);
382 for (lease
= leases
; lease
; lease
= lease
->next
)
383 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)) &&
384 is_same_net(local
, lease
->addr
, netmask
) &&
385 prefix
> lease
->new_prefixlen
)
387 lease
->new_interface
= if_index
;
388 lease
->new_prefixlen
= prefix
;
395 static int find_interface_v6(struct in6_addr
*local
, int prefix
,
396 int scope
, int if_index
, int flags
,
397 int preferred
, int valid
, void *vparam
)
399 struct dhcp_lease
*lease
;
407 for (lease
= leases
; lease
; lease
= lease
->next
)
408 if ((lease
->flags
& (LEASE_TA
| LEASE_NA
)))
409 if (is_same_net6(local
, &lease
->addr6
, prefix
) && prefix
> lease
->new_prefixlen
) {
410 /* save prefix length for comparison, as we might get shorter matching
411 * prefix in upcoming netlink GETADDR responses
413 lease
->new_interface
= if_index
;
414 lease
->new_prefixlen
= prefix
;
420 void lease_ping_reply(struct in6_addr
*sender
, unsigned char *packet
, char *interface
)
422 /* We may be doing RA but not DHCPv4, in which case the lease
423 database may not exist and we have nothing to do anyway */
425 slaac_ping_reply(sender
, packet
, interface
, leases
);
428 void lease_update_slaac(time_t now
)
430 /* Called when we contruct a new RA-names context, to add putative
431 new SLAAC addresses to existing leases. */
433 struct dhcp_lease
*lease
;
436 for (lease
= leases
; lease
; lease
= lease
->next
)
437 slaac_add_addrs(lease
, now
, 0);
443 /* Find interfaces associated with leases at start-up. This gets updated as
444 we do DHCP transactions, but information about directly-connected subnets
445 is useful from scrips and necessary for determining SLAAC addresses from
447 void lease_find_interfaces(time_t now
)
449 struct dhcp_lease
*lease
;
451 for (lease
= leases
; lease
; lease
= lease
->next
)
452 lease
->new_prefixlen
= lease
->new_interface
= 0;
454 iface_enumerate(AF_INET
, &now
, find_interface_v4
);
456 iface_enumerate(AF_INET6
, &now
, find_interface_v6
);
459 for (lease
= leases
; lease
; lease
= lease
->next
)
460 if (lease
->new_interface
!= 0)
461 lease_set_interface(lease
, lease
->new_interface
, now
);
465 void lease_make_duid(time_t now
)
467 /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
468 if (!daemon
->duid
&& daemon
->doing_dhcp6
)
479 void lease_update_dns(int force
)
481 struct dhcp_lease
*lease
;
483 if (daemon
->port
!= 0 && (dns_dirty
|| force
))
485 #ifndef HAVE_BROKEN_RTC
486 /* force transfer to authoritative secondaries */
492 for (lease
= leases
; lease
; lease
= lease
->next
)
497 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
499 else if (lease
->hostname
|| lease
->fqdn
)
501 struct slaac_address
*slaac
;
503 for (slaac
= lease
->slaac_address
; slaac
; slaac
= slaac
->next
)
504 if (slaac
->backoff
== 0)
507 cache_add_dhcp_entry(lease
->fqdn
, AF_INET6
, (struct all_addr
*)&slaac
->addr
, lease
->expires
);
508 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
509 cache_add_dhcp_entry(lease
->hostname
, AF_INET6
, (struct all_addr
*)&slaac
->addr
, lease
->expires
);
514 cache_add_dhcp_entry(lease
->fqdn
, prot
,
515 prot
== AF_INET
? (struct all_addr
*)&lease
->addr
: (struct all_addr
*)&lease
->addr6
,
518 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
519 cache_add_dhcp_entry(lease
->hostname
, prot
,
520 prot
== AF_INET
? (struct all_addr
*)&lease
->addr
: (struct all_addr
*)&lease
->addr6
,
525 cache_add_dhcp_entry(lease
->fqdn
, prot
, (struct all_addr
*)&lease
->addr
, lease
->expires
);
527 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
528 cache_add_dhcp_entry(lease
->hostname
, prot
, (struct all_addr
*)&lease
->addr
, lease
->expires
);
536 void lease_prune(struct dhcp_lease
*target
, time_t now
)
538 struct dhcp_lease
*lease
, *tmp
, **up
;
540 for (lease
= leases
, up
= &leases
; lease
; lease
= tmp
)
543 if ((lease
->expires
!= 0 && difftime(now
, lease
->expires
) > 0) || lease
== target
)
549 *up
= lease
->next
; /* unlink */
551 /* Put on old_leases list 'till we
552 can run the script */
553 lease
->next
= old_leases
;
564 struct dhcp_lease
*lease_find_by_client(unsigned char *hwaddr
, int hw_len
, int hw_type
,
565 unsigned char *clid
, int clid_len
)
567 struct dhcp_lease
*lease
;
570 for (lease
= leases
; lease
; lease
= lease
->next
)
573 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
576 if (lease
->clid
&& clid_len
== lease
->clid_len
&&
577 memcmp(clid
, lease
->clid
, clid_len
) == 0)
581 for (lease
= leases
; lease
; lease
= lease
->next
)
584 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
587 if ((!lease
->clid
|| !clid
) &&
589 lease
->hwaddr_len
== hw_len
&&
590 lease
->hwaddr_type
== hw_type
&&
591 memcmp(hwaddr
, lease
->hwaddr
, hw_len
) == 0)
598 struct dhcp_lease
*lease_find_by_addr(struct in_addr addr
)
600 struct dhcp_lease
*lease
;
602 for (lease
= leases
; lease
; lease
= lease
->next
)
605 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
608 if (lease
->addr
.s_addr
== addr
.s_addr
)
616 /* find address for {CLID, IAID, address} */
617 struct dhcp_lease
*lease6_find(unsigned char *clid
, int clid_len
,
618 int lease_type
, int iaid
, struct in6_addr
*addr
)
620 struct dhcp_lease
*lease
;
622 for (lease
= leases
; lease
; lease
= lease
->next
)
624 if (!(lease
->flags
& lease_type
) || lease
->iaid
!= iaid
)
627 if (!IN6_ARE_ADDR_EQUAL(&lease
->addr6
, addr
))
630 if ((clid_len
!= lease
->clid_len
||
631 memcmp(clid
, lease
->clid
, clid_len
) != 0))
640 /* reset "USED flags */
641 void lease6_reset(void)
643 struct dhcp_lease
*lease
;
645 for (lease
= leases
; lease
; lease
= lease
->next
)
646 lease
->flags
&= ~LEASE_USED
;
649 /* enumerate all leases belonging to {CLID, IAID} */
650 struct dhcp_lease
*lease6_find_by_client(struct dhcp_lease
*first
, int lease_type
, unsigned char *clid
, int clid_len
, int iaid
)
652 struct dhcp_lease
*lease
;
659 for (lease
= first
; lease
; lease
= lease
->next
)
661 if (lease
->flags
& LEASE_USED
)
664 if (!(lease
->flags
& lease_type
) || lease
->iaid
!= iaid
)
667 if ((clid_len
!= lease
->clid_len
||
668 memcmp(clid
, lease
->clid
, clid_len
) != 0))
677 struct dhcp_lease
*lease6_find_by_addr(struct in6_addr
*net
, int prefix
, u64 addr
)
679 struct dhcp_lease
*lease
;
681 for (lease
= leases
; lease
; lease
= lease
->next
)
683 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
686 if (is_same_net6(&lease
->addr6
, net
, prefix
) &&
687 (prefix
== 128 || addr6part(&lease
->addr6
) == addr
))
694 /* Find largest assigned address in context */
695 u64
lease_find_max_addr6(struct dhcp_context
*context
)
697 struct dhcp_lease
*lease
;
698 u64 addr
= addr6part(&context
->start6
);
700 if (!(context
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
)))
701 for (lease
= leases
; lease
; lease
= lease
->next
)
703 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
706 if (is_same_net6(&lease
->addr6
, &context
->start6
, 64) &&
707 addr6part(&lease
->addr6
) > addr6part(&context
->start6
) &&
708 addr6part(&lease
->addr6
) <= addr6part(&context
->end6
) &&
709 addr6part(&lease
->addr6
) > addr
)
710 addr
= addr6part(&lease
->addr6
);
718 /* Find largest assigned address in context */
719 struct in_addr
lease_find_max_addr(struct dhcp_context
*context
)
721 struct dhcp_lease
*lease
;
722 struct in_addr addr
= context
->start
;
724 if (!(context
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
)))
725 for (lease
= leases
; lease
; lease
= lease
->next
)
728 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
731 if (((unsigned)ntohl(lease
->addr
.s_addr
)) > ((unsigned)ntohl(context
->start
.s_addr
)) &&
732 ((unsigned)ntohl(lease
->addr
.s_addr
)) <= ((unsigned)ntohl(context
->end
.s_addr
)) &&
733 ((unsigned)ntohl(lease
->addr
.s_addr
)) > ((unsigned)ntohl(addr
.s_addr
)))
740 static struct dhcp_lease
*lease_allocate(void)
742 struct dhcp_lease
*lease
;
743 if (!leases_left
|| !(lease
= whine_malloc(sizeof(struct dhcp_lease
))))
746 memset(lease
, 0, sizeof(struct dhcp_lease
));
747 lease
->flags
= LEASE_NEW
;
749 #ifdef HAVE_BROKEN_RTC
750 lease
->length
= 0xffffffff; /* illegal value */
752 lease
->hwaddr_len
= 256; /* illegal value */
753 lease
->next
= leases
;
762 struct dhcp_lease
*lease4_allocate(struct in_addr addr
)
764 struct dhcp_lease
*lease
= lease_allocate();
772 struct dhcp_lease
*lease6_allocate(struct in6_addr
*addrp
, int lease_type
)
774 struct dhcp_lease
*lease
= lease_allocate();
778 lease
->addr6
= *addrp
;
779 lease
->flags
|= lease_type
;
787 void lease_set_expires(struct dhcp_lease
*lease
, unsigned int len
, time_t now
)
791 if (len
== 0xffffffff)
798 exp
= now
+ (time_t)len
;
799 /* Check for 2038 overflow. Make the lease
800 inifinite in that case, as the least disruptive
802 if (difftime(exp
, now
) <= 0.0)
806 if (exp
!= lease
->expires
)
809 lease
->expires
= exp
;
810 #ifndef HAVE_BROKEN_RTC
811 lease
->flags
|= LEASE_AUX_CHANGED
;
816 #ifdef HAVE_BROKEN_RTC
817 if (len
!= lease
->length
)
820 lease
->flags
|= LEASE_AUX_CHANGED
;
827 void lease_set_iaid(struct dhcp_lease
*lease
, int iaid
)
829 if (lease
->iaid
!= iaid
)
832 lease
->flags
|= LEASE_CHANGED
;
837 void lease_set_hwaddr(struct dhcp_lease
*lease
, unsigned char *hwaddr
,
838 unsigned char *clid
, int hw_len
, int hw_type
, int clid_len
,
839 time_t now
, int force
)
843 lease
->flags
|= LEASE_HAVE_HWADDR
;
849 if (hw_len
!= lease
->hwaddr_len
||
850 hw_type
!= lease
->hwaddr_type
||
851 (hw_len
!= 0 && memcmp(lease
->hwaddr
, hwaddr
, hw_len
) != 0))
854 memcpy(lease
->hwaddr
, hwaddr
, hw_len
);
855 lease
->hwaddr_len
= hw_len
;
856 lease
->hwaddr_type
= hw_type
;
857 lease
->flags
|= LEASE_CHANGED
;
858 file_dirty
= 1; /* run script on change */
861 /* only update clid when one is available, stops packets
862 without a clid removing the record. Lease init uses
863 clid_len == 0 for no clid. */
864 if (clid_len
!= 0 && clid
)
869 if (lease
->clid_len
!= clid_len
)
871 lease
->flags
|= LEASE_AUX_CHANGED
;
874 if (!(lease
->clid
= whine_malloc(clid_len
)))
880 else if (memcmp(lease
->clid
, clid
, clid_len
) != 0)
882 lease
->flags
|= LEASE_AUX_CHANGED
;
889 lease
->clid_len
= clid_len
;
890 memcpy(lease
->clid
, clid
, clid_len
);
895 slaac_add_addrs(lease
, now
, force
);
899 static void kill_name(struct dhcp_lease
*lease
)
901 /* run script to say we lost our old name */
903 /* this shouldn't happen unless updates are very quick and the
904 script very slow, we just avoid a memory leak if it does. */
905 free(lease
->old_hostname
);
907 /* If we know the fqdn, pass that. The helper will derive the
908 unqualified name from it, free the unqualified name here. */
912 lease
->old_hostname
= lease
->fqdn
;
913 free(lease
->hostname
);
916 lease
->old_hostname
= lease
->hostname
;
918 lease
->hostname
= lease
->fqdn
= NULL
;
921 void lease_set_hostname(struct dhcp_lease
*lease
, char *name
, int auth
, char *domain
, char *config_domain
)
923 struct dhcp_lease
*lease_tmp
;
924 char *new_name
= NULL
, *new_fqdn
= NULL
;
926 if (config_domain
&& (!domain
|| !hostname_isequal(domain
, config_domain
)))
927 my_syslog(MS_DHCP
| LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), config_domain
, name
);
929 if (lease
->hostname
&& name
&& hostname_isequal(lease
->hostname
, name
))
932 lease
->flags
|= LEASE_AUTH_NAME
;
936 if (!name
&& !lease
->hostname
)
939 /* If a machine turns up on a new net without dropping the old lease,
940 or two machines claim the same name, then we end up with two interfaces with
941 the same name. Check for that here and remove the name from the old lease.
942 Note that IPv6 leases are different. All the leases to the same DUID are
943 allowed the same name.
945 Don't allow a name from the client to override a name from dnsmasq config. */
949 if ((new_name
= whine_malloc(strlen(name
) + 1)))
951 strcpy(new_name
, name
);
952 if (domain
&& (new_fqdn
= whine_malloc(strlen(new_name
) + strlen(domain
) + 2)))
954 strcpy(new_fqdn
, name
);
955 strcat(new_fqdn
, ".");
956 strcat(new_fqdn
, domain
);
960 /* Depending on mode, we check either unqualified name or FQDN. */
961 for (lease_tmp
= leases
; lease_tmp
; lease_tmp
= lease_tmp
->next
)
963 if (option_bool(OPT_DHCP_FQDN
))
965 if (!new_fqdn
|| !lease_tmp
->fqdn
|| !hostname_isequal(lease_tmp
->fqdn
, new_fqdn
))
970 if (!new_name
|| !lease_tmp
->hostname
|| !hostname_isequal(lease_tmp
->hostname
, new_name
) )
974 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
976 if (!(lease_tmp
->flags
& (LEASE_TA
| LEASE_NA
)))
979 /* another lease for the same DUID is OK for IPv6 */
980 if (lease
->clid_len
== lease_tmp
->clid_len
&&
981 lease
->clid
&& lease_tmp
->clid
&&
982 memcmp(lease
->clid
, lease_tmp
->clid
, lease
->clid_len
) == 0)
985 else if (lease_tmp
->flags
& (LEASE_TA
| LEASE_NA
))
988 if ((lease_tmp
->flags
& LEASE_AUTH_NAME
) && !auth
)
995 kill_name(lease_tmp
);
1000 if (lease
->hostname
)
1003 lease
->hostname
= new_name
;
1004 lease
->fqdn
= new_fqdn
;
1007 lease
->flags
|= LEASE_AUTH_NAME
;
1011 lease
->flags
|= LEASE_CHANGED
; /* run script on change */
1014 void lease_set_interface(struct dhcp_lease
*lease
, int interface
, time_t now
)
1018 if (lease
->last_interface
== interface
)
1021 lease
->last_interface
= interface
;
1022 lease
->flags
|= LEASE_CHANGED
;
1025 slaac_add_addrs(lease
, now
, 0);
1029 void rerun_scripts(void)
1031 struct dhcp_lease
*lease
;
1033 for (lease
= leases
; lease
; lease
= lease
->next
)
1034 lease
->flags
|= LEASE_CHANGED
;
1037 /* deleted leases get transferred to the old_leases list.
1038 remove them here, after calling the lease change
1039 script. Also run the lease change script on new/modified leases.
1041 Return zero if nothing to do. */
1042 int do_script_run(time_t now
)
1044 struct dhcp_lease
*lease
;
1049 /* If we're going to be sending DBus signals, but the connection is not yet up,
1050 delay everything until it is. */
1051 if (option_bool(OPT_DBUS
) && !daemon
->dbus
)
1059 /* If the lease still has an old_hostname, do the "old" action on that first */
1060 if (lease
->old_hostname
)
1063 queue_script(ACTION_OLD_HOSTNAME
, lease
, lease
->old_hostname
, now
);
1065 free(lease
->old_hostname
);
1066 lease
->old_hostname
= NULL
;
1072 struct slaac_address
*slaac
, *tmp
;
1073 for (slaac
= lease
->slaac_address
; slaac
; slaac
= tmp
)
1081 queue_script(ACTION_DEL
, lease
, lease
->old_hostname
, now
);
1084 emit_dbus_signal(ACTION_DEL
, lease
, lease
->old_hostname
);
1086 old_leases
= lease
->next
;
1088 free(lease
->old_hostname
);
1090 free(lease
->extradata
);
1097 /* make sure we announce the loss of a hostname before its new location. */
1098 for (lease
= leases
; lease
; lease
= lease
->next
)
1099 if (lease
->old_hostname
)
1102 queue_script(ACTION_OLD_HOSTNAME
, lease
, lease
->old_hostname
, now
);
1104 free(lease
->old_hostname
);
1105 lease
->old_hostname
= NULL
;
1109 for (lease
= leases
; lease
; lease
= lease
->next
)
1110 if ((lease
->flags
& (LEASE_NEW
| LEASE_CHANGED
)) ||
1111 ((lease
->flags
& LEASE_AUX_CHANGED
) && option_bool(OPT_LEASE_RO
)))
1114 queue_script((lease
->flags
& LEASE_NEW
) ? ACTION_ADD
: ACTION_OLD
, lease
,
1115 lease
->fqdn
? lease
->fqdn
: lease
->hostname
, now
);
1118 emit_dbus_signal((lease
->flags
& LEASE_NEW
) ? ACTION_ADD
: ACTION_OLD
, lease
,
1119 lease
->fqdn
? lease
->fqdn
: lease
->hostname
);
1121 lease
->flags
&= ~(LEASE_NEW
| LEASE_CHANGED
| LEASE_AUX_CHANGED
);
1123 /* this is used for the "add" call, then junked, since they're not in the database */
1124 free(lease
->extradata
);
1125 lease
->extradata
= NULL
;
1130 return 0; /* nothing to do */
1134 void lease_add_extradata(struct dhcp_lease
*lease
, unsigned char *data
, unsigned int len
, int delim
)
1138 /* check for embeded NULLs */
1139 for (i
= 0; i
< len
; i
++)
1146 if ((lease
->extradata_size
- lease
->extradata_len
) < (len
+ 1))
1148 size_t newsz
= lease
->extradata_len
+ len
+ 100;
1149 unsigned char *new = whine_malloc(newsz
);
1154 if (lease
->extradata
)
1156 memcpy(new, lease
->extradata
, lease
->extradata_len
);
1157 free(lease
->extradata
);
1160 lease
->extradata
= new;
1161 lease
->extradata_size
= newsz
;
1165 memcpy(lease
->extradata
+ lease
->extradata_len
, data
, len
);
1166 lease
->extradata
[lease
->extradata_len
+ len
] = delim
;
1167 lease
->extradata_len
+= len
+ 1;
1173 void tomato_helper(time_t now
)
1178 struct dhcp_lease
*lease
;
1180 // if delete exists...
1181 if ((f
= fopen("/var/tmp/dhcp/delete", "r")) != NULL
) {
1182 while (fgets(buf
, sizeof(buf
), f
)) {
1183 ia
.s_addr
= inet_addr(buf
);
1184 lease
= lease_find_by_addr(ia
);
1186 lease_prune(lease
, 0);
1187 lease_update_file(now
);
1191 unlink("/var/tmp/dhcp/delete");
1194 // dump the leases file
1195 if ((f
= fopen("/var/tmp/dhcp/leases.!", "w")) != NULL
) {
1196 for (lease
= leases
; lease
; lease
= lease
->next
) {
1197 if (lease
->hwaddr_type
== ARPHRD_ETHER
) {
1198 #ifdef HAVE_DHCP6 //only dump dhcpv6 if we have it
1199 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
1200 inet_ntop(AF_INET6
, &lease
->addr6
, buf
, ADDRSTRLEN
);
1202 #endif // Thanks to Shibby :-)
1203 inet_ntop(AF_INET
, &lease
->addr
, buf
, ADDRSTRLEN
);
1205 fprintf(f
, "%lu %02X:%02X:%02X:%02X:%02X:%02X %s %s\n",
1206 lease
->expires
- now
,
1207 lease
->hwaddr
[0], lease
->hwaddr
[1], lease
->hwaddr
[2], lease
->hwaddr
[3], lease
->hwaddr
[4], lease
->hwaddr
[5],
1209 ((lease
->hostname
) && (strlen(lease
->hostname
) > 0)) ? lease
->hostname
: "*");
1213 rename("/var/tmp/dhcp/leases.!", "/var/tmp/dhcp/leases");
1216 #endif //HAVE_TOMATO
1218 #ifdef HAVE_LEASEFILE_EXPIRE
1219 void flush_lease_file(time_t now
)
1221 static time_t flush_time
= (time_t)0;
1223 if(difftime(flush_time
, now
) < 0)
1226 lease_prune(NULL
, now
);
1227 lease_update_file(now
);
1229 if (file_dirty
== 0)
1232 #endif //HAVE_LEASEFILE_EXPIRE