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 //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_RT
146 /* strictly time_t is opaque, but this hack should work on all sane systems,
147 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 + slop. */
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
+ 10) > 0.0))
356 next_event
= lease
->expires
+ 10;
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
;
381 for (lease
= leases
; lease
; lease
= lease
->next
)
382 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
383 if (is_same_net(local
, lease
->addr
, netmask
))
384 lease_set_interface(lease
, if_index
, *((time_t *)vparam
));
390 static int find_interface_v6(struct in6_addr
*local
, int prefix
,
391 int scope
, int if_index
, int flags
,
392 int preferred
, int valid
, void *vparam
)
394 struct dhcp_lease
*lease
;
401 for (lease
= leases
; lease
; lease
= lease
->next
)
402 if ((lease
->flags
& (LEASE_TA
| LEASE_NA
)))
403 if (is_same_net6(local
, &lease
->addr6
, prefix
))
404 lease_set_interface(lease
, if_index
, *((time_t *)vparam
));
409 void lease_ping_reply(struct in6_addr
*sender
, unsigned char *packet
, char *interface
)
411 /* We may be doing RA but not DHCPv4, in which case the lease
412 database may not exist and we have nothing to do anyway */
414 slaac_ping_reply(sender
, packet
, interface
, leases
);
417 void lease_update_slaac(time_t now
)
419 /* Called when we contruct a new RA-names context, to add putative
420 new SLAAC addresses to existing leases. */
422 struct dhcp_lease
*lease
;
425 for (lease
= leases
; lease
; lease
= lease
->next
)
426 slaac_add_addrs(lease
, now
, 0);
432 /* Find interfaces associated with leases at start-up. This gets updated as
433 we do DHCP transactions, but information about directly-connected subnets
434 is useful from scrips and necessary for determining SLAAC addresses from
436 void lease_find_interfaces(time_t now
)
438 iface_enumerate(AF_INET
, &now
, find_interface_v4
);
440 iface_enumerate(AF_INET6
, &now
, find_interface_v6
);
442 /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
443 if (!daemon
->duid
&& daemon
->dhcp6
)
453 void lease_update_dns(int force
)
455 struct dhcp_lease
*lease
;
457 if (daemon
->port
!= 0 && (dns_dirty
|| force
))
459 #ifndef HAVE_BROKEN_RTC
460 /* force transfer to authoritative secondaries */
466 for (lease
= leases
; lease
; lease
= lease
->next
)
471 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
473 else if (lease
->hostname
|| lease
->fqdn
)
475 struct slaac_address
*slaac
;
477 for (slaac
= lease
->slaac_address
; slaac
; slaac
= slaac
->next
)
478 if (slaac
->backoff
== 0)
481 cache_add_dhcp_entry(lease
->fqdn
, AF_INET6
, (struct all_addr
*)&slaac
->addr
, lease
->expires
);
482 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
483 cache_add_dhcp_entry(lease
->hostname
, AF_INET6
, (struct all_addr
*)&slaac
->addr
, lease
->expires
);
488 cache_add_dhcp_entry(lease
->fqdn
, prot
,
489 prot
== AF_INET
? (struct all_addr
*)&lease
->addr
: (struct all_addr
*)&lease
->addr6
,
492 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
493 cache_add_dhcp_entry(lease
->hostname
, prot
,
494 prot
== AF_INET
? (struct all_addr
*)&lease
->addr
: (struct all_addr
*)&lease
->addr6
,
499 cache_add_dhcp_entry(lease
->fqdn
, prot
, (struct all_addr
*)&lease
->addr
, lease
->expires
);
501 if (!option_bool(OPT_DHCP_FQDN
) && lease
->hostname
)
502 cache_add_dhcp_entry(lease
->hostname
, prot
, (struct all_addr
*)&lease
->addr
, lease
->expires
);
510 void lease_prune(struct dhcp_lease
*target
, time_t now
)
512 struct dhcp_lease
*lease
, *tmp
, **up
;
514 for (lease
= leases
, up
= &leases
; lease
; lease
= tmp
)
517 if ((lease
->expires
!= 0 && difftime(now
, lease
->expires
) > 0) || lease
== target
)
523 *up
= lease
->next
; /* unlink */
525 /* Put on old_leases list 'till we
526 can run the script */
527 lease
->next
= old_leases
;
538 struct dhcp_lease
*lease_find_by_client(unsigned char *hwaddr
, int hw_len
, int hw_type
,
539 unsigned char *clid
, int clid_len
)
541 struct dhcp_lease
*lease
;
544 for (lease
= leases
; lease
; lease
= lease
->next
)
547 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
550 if (lease
->clid
&& clid_len
== lease
->clid_len
&&
551 memcmp(clid
, lease
->clid
, clid_len
) == 0)
555 for (lease
= leases
; lease
; lease
= lease
->next
)
558 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
561 if ((!lease
->clid
|| !clid
) &&
563 lease
->hwaddr_len
== hw_len
&&
564 lease
->hwaddr_type
== hw_type
&&
565 memcmp(hwaddr
, lease
->hwaddr
, hw_len
) == 0)
572 struct dhcp_lease
*lease_find_by_addr(struct in_addr addr
)
574 struct dhcp_lease
*lease
;
576 for (lease
= leases
; lease
; lease
= lease
->next
)
579 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
582 if (lease
->addr
.s_addr
== addr
.s_addr
)
590 /* find address for {CLID, IAID, address} */
591 struct dhcp_lease
*lease6_find(unsigned char *clid
, int clid_len
,
592 int lease_type
, int iaid
, struct in6_addr
*addr
)
594 struct dhcp_lease
*lease
;
596 for (lease
= leases
; lease
; lease
= lease
->next
)
598 if (!(lease
->flags
& lease_type
) || lease
->iaid
!= iaid
)
601 if (!IN6_ARE_ADDR_EQUAL(&lease
->addr6
, addr
))
604 if ((clid_len
!= lease
->clid_len
||
605 memcmp(clid
, lease
->clid
, clid_len
) != 0))
614 /* reset "USED flags */
615 void lease6_reset(void)
617 struct dhcp_lease
*lease
;
619 for (lease
= leases
; lease
; lease
= lease
->next
)
620 lease
->flags
&= ~LEASE_USED
;
623 /* enumerate all leases belonging to {CLID, IAID} */
624 struct dhcp_lease
*lease6_find_by_client(struct dhcp_lease
*first
, int lease_type
, unsigned char *clid
, int clid_len
, int iaid
)
626 struct dhcp_lease
*lease
;
633 for (lease
= first
; lease
; lease
= lease
->next
)
635 if (lease
->flags
& LEASE_USED
)
638 if (!(lease
->flags
& lease_type
) || lease
->iaid
!= iaid
)
641 if ((clid_len
!= lease
->clid_len
||
642 memcmp(clid
, lease
->clid
, clid_len
) != 0))
651 struct dhcp_lease
*lease6_find_by_addr(struct in6_addr
*net
, int prefix
, u64 addr
)
653 struct dhcp_lease
*lease
;
655 for (lease
= leases
; lease
; lease
= lease
->next
)
657 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
660 if (is_same_net6(&lease
->addr6
, net
, prefix
) &&
661 (prefix
== 128 || addr6part(&lease
->addr6
) == addr
))
668 /* Find largest assigned address in context */
669 u64
lease_find_max_addr6(struct dhcp_context
*context
)
671 struct dhcp_lease
*lease
;
672 u64 addr
= addr6part(&context
->start6
);
674 if (!(context
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
)))
675 for (lease
= leases
; lease
; lease
= lease
->next
)
677 if (!(lease
->flags
& (LEASE_TA
| LEASE_NA
)))
680 if (is_same_net6(&lease
->addr6
, &context
->start6
, 64) &&
681 addr6part(&lease
->addr6
) > addr6part(&context
->start6
) &&
682 addr6part(&lease
->addr6
) <= addr6part(&context
->end6
) &&
683 addr6part(&lease
->addr6
) > addr
)
684 addr
= addr6part(&lease
->addr6
);
692 /* Find largest assigned address in context */
693 struct in_addr
lease_find_max_addr(struct dhcp_context
*context
)
695 struct dhcp_lease
*lease
;
696 struct in_addr addr
= context
->start
;
698 if (!(context
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
)))
699 for (lease
= leases
; lease
; lease
= lease
->next
)
702 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
705 if (((unsigned)ntohl(lease
->addr
.s_addr
)) > ((unsigned)ntohl(context
->start
.s_addr
)) &&
706 ((unsigned)ntohl(lease
->addr
.s_addr
)) <= ((unsigned)ntohl(context
->end
.s_addr
)) &&
707 ((unsigned)ntohl(lease
->addr
.s_addr
)) > ((unsigned)ntohl(addr
.s_addr
)))
714 static struct dhcp_lease
*lease_allocate(void)
716 struct dhcp_lease
*lease
;
717 if (!leases_left
|| !(lease
= whine_malloc(sizeof(struct dhcp_lease
))))
720 memset(lease
, 0, sizeof(struct dhcp_lease
));
721 lease
->flags
= LEASE_NEW
;
723 #ifdef HAVE_BROKEN_RTC
724 lease
->length
= 0xffffffff; /* illegal value */
726 lease
->hwaddr_len
= 256; /* illegal value */
727 lease
->next
= leases
;
736 struct dhcp_lease
*lease4_allocate(struct in_addr addr
)
738 struct dhcp_lease
*lease
= lease_allocate();
746 struct dhcp_lease
*lease6_allocate(struct in6_addr
*addrp
, int lease_type
)
748 struct dhcp_lease
*lease
= lease_allocate();
752 lease
->addr6
= *addrp
;
753 lease
->flags
|= lease_type
;
761 void lease_set_expires(struct dhcp_lease
*lease
, unsigned int len
, time_t now
)
763 time_t exp
= now
+ (time_t)len
;
765 if (len
== 0xffffffff)
771 if (exp
!= lease
->expires
)
774 lease
->expires
= exp
;
775 #ifndef HAVE_BROKEN_RTC
776 lease
->flags
|= LEASE_AUX_CHANGED
;
781 #ifdef HAVE_BROKEN_RTC
782 if (len
!= lease
->length
)
785 lease
->flags
|= LEASE_AUX_CHANGED
;
792 void lease_set_iaid(struct dhcp_lease
*lease
, int iaid
)
794 if (lease
->iaid
!= iaid
)
797 lease
->flags
|= LEASE_CHANGED
;
802 void lease_set_hwaddr(struct dhcp_lease
*lease
, unsigned char *hwaddr
,
803 unsigned char *clid
, int hw_len
, int hw_type
, int clid_len
,
804 time_t now
, int force
)
808 lease
->flags
|= LEASE_HAVE_HWADDR
;
814 if (hw_len
!= lease
->hwaddr_len
||
815 hw_type
!= lease
->hwaddr_type
||
816 (hw_len
!= 0 && memcmp(lease
->hwaddr
, hwaddr
, hw_len
) != 0))
819 memcpy(lease
->hwaddr
, hwaddr
, hw_len
);
820 lease
->hwaddr_len
= hw_len
;
821 lease
->hwaddr_type
= hw_type
;
822 lease
->flags
|= LEASE_CHANGED
;
823 file_dirty
= 1; /* run script on change */
826 /* only update clid when one is available, stops packets
827 without a clid removing the record. Lease init uses
828 clid_len == 0 for no clid. */
829 if (clid_len
!= 0 && clid
)
834 if (lease
->clid_len
!= clid_len
)
836 lease
->flags
|= LEASE_AUX_CHANGED
;
839 if (!(lease
->clid
= whine_malloc(clid_len
)))
845 else if (memcmp(lease
->clid
, clid
, clid_len
) != 0)
847 lease
->flags
|= LEASE_AUX_CHANGED
;
854 lease
->clid_len
= clid_len
;
855 memcpy(lease
->clid
, clid
, clid_len
);
860 slaac_add_addrs(lease
, now
, force
);
864 static void kill_name(struct dhcp_lease
*lease
)
866 /* run script to say we lost our old name */
868 /* this shouldn't happen unless updates are very quick and the
869 script very slow, we just avoid a memory leak if it does. */
870 free(lease
->old_hostname
);
872 /* If we know the fqdn, pass that. The helper will derive the
873 unqualified name from it, free the unqualified name here. */
877 lease
->old_hostname
= lease
->fqdn
;
878 free(lease
->hostname
);
881 lease
->old_hostname
= lease
->hostname
;
883 lease
->hostname
= lease
->fqdn
= NULL
;
886 void lease_set_hostname(struct dhcp_lease
*lease
, char *name
, int auth
, char *domain
, char *config_domain
)
888 struct dhcp_lease
*lease_tmp
;
889 char *new_name
= NULL
, *new_fqdn
= NULL
;
891 if (config_domain
&& (!domain
|| !hostname_isequal(domain
, config_domain
)))
892 my_syslog(MS_DHCP
| LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), config_domain
, name
);
894 if (lease
->hostname
&& name
&& hostname_isequal(lease
->hostname
, name
))
897 lease
->flags
|= LEASE_AUTH_NAME
;
901 if (!name
&& !lease
->hostname
)
904 /* If a machine turns up on a new net without dropping the old lease,
905 or two machines claim the same name, then we end up with two interfaces with
906 the same name. Check for that here and remove the name from the old lease.
907 Note that IPv6 leases are different. All the leases to the same DUID are
908 allowed the same name.
910 Don't allow a name from the client to override a name from dnsmasq config. */
914 if ((new_name
= whine_malloc(strlen(name
) + 1)))
916 strcpy(new_name
, name
);
917 if (domain
&& (new_fqdn
= whine_malloc(strlen(new_name
) + strlen(domain
) + 2)))
919 strcpy(new_fqdn
, name
);
920 strcat(new_fqdn
, ".");
921 strcat(new_fqdn
, domain
);
925 /* Depending on mode, we check either unqualified name or FQDN. */
926 for (lease_tmp
= leases
; lease_tmp
; lease_tmp
= lease_tmp
->next
)
928 if (option_bool(OPT_DHCP_FQDN
))
930 if (!new_fqdn
|| !lease_tmp
->fqdn
|| !hostname_isequal(lease_tmp
->fqdn
, new_fqdn
))
935 if (!new_name
|| !lease_tmp
->hostname
|| !hostname_isequal(lease_tmp
->hostname
, new_name
) )
939 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
941 if (!(lease_tmp
->flags
& (LEASE_TA
| LEASE_NA
)))
944 /* another lease for the same DUID is OK for IPv6 */
945 if (lease
->clid_len
== lease_tmp
->clid_len
&&
946 lease
->clid
&& lease_tmp
->clid
&&
947 memcmp(lease
->clid
, lease_tmp
->clid
, lease
->clid_len
) == 0)
950 else if (lease_tmp
->flags
& (LEASE_TA
| LEASE_NA
))
953 if ((lease_tmp
->flags
& LEASE_AUTH_NAME
) && !auth
)
960 kill_name(lease_tmp
);
968 lease
->hostname
= new_name
;
969 lease
->fqdn
= new_fqdn
;
972 lease
->flags
|= LEASE_AUTH_NAME
;
976 lease
->flags
|= LEASE_CHANGED
; /* run script on change */
979 void lease_set_interface(struct dhcp_lease
*lease
, int interface
, time_t now
)
983 if (lease
->last_interface
== interface
)
986 lease
->last_interface
= interface
;
987 lease
->flags
|= LEASE_CHANGED
;
990 slaac_add_addrs(lease
, now
, 0);
994 void rerun_scripts(void)
996 struct dhcp_lease
*lease
;
998 for (lease
= leases
; lease
; lease
= lease
->next
)
999 lease
->flags
|= LEASE_CHANGED
;
1002 /* deleted leases get transferred to the old_leases list.
1003 remove them here, after calling the lease change
1004 script. Also run the lease change script on new/modified leases.
1006 Return zero if nothing to do. */
1007 int do_script_run(time_t now
)
1009 struct dhcp_lease
*lease
;
1014 /* If we're going to be sending DBus signals, but the connection is not yet up,
1015 delay everything until it is. */
1016 if (option_bool(OPT_DBUS
) && !daemon
->dbus
)
1024 /* If the lease still has an old_hostname, do the "old" action on that first */
1025 if (lease
->old_hostname
)
1028 queue_script(ACTION_OLD_HOSTNAME
, lease
, lease
->old_hostname
, now
);
1030 free(lease
->old_hostname
);
1031 lease
->old_hostname
= NULL
;
1037 struct slaac_address
*slaac
, *tmp
;
1038 for (slaac
= lease
->slaac_address
; slaac
; slaac
= tmp
)
1046 queue_script(ACTION_DEL
, lease
, lease
->old_hostname
, now
);
1049 emit_dbus_signal(ACTION_DEL
, lease
, lease
->old_hostname
);
1051 old_leases
= lease
->next
;
1053 free(lease
->old_hostname
);
1055 free(lease
->extradata
);
1062 /* make sure we announce the loss of a hostname before its new location. */
1063 for (lease
= leases
; lease
; lease
= lease
->next
)
1064 if (lease
->old_hostname
)
1067 queue_script(ACTION_OLD_HOSTNAME
, lease
, lease
->old_hostname
, now
);
1069 free(lease
->old_hostname
);
1070 lease
->old_hostname
= NULL
;
1074 for (lease
= leases
; lease
; lease
= lease
->next
)
1075 if ((lease
->flags
& (LEASE_NEW
| LEASE_CHANGED
)) ||
1076 ((lease
->flags
& LEASE_AUX_CHANGED
) && option_bool(OPT_LEASE_RO
)))
1079 queue_script((lease
->flags
& LEASE_NEW
) ? ACTION_ADD
: ACTION_OLD
, lease
,
1080 lease
->fqdn
? lease
->fqdn
: lease
->hostname
, now
);
1083 emit_dbus_signal((lease
->flags
& LEASE_NEW
) ? ACTION_ADD
: ACTION_OLD
, lease
,
1084 lease
->fqdn
? lease
->fqdn
: lease
->hostname
);
1086 lease
->flags
&= ~(LEASE_NEW
| LEASE_CHANGED
| LEASE_AUX_CHANGED
);
1088 /* this is used for the "add" call, then junked, since they're not in the database */
1089 free(lease
->extradata
);
1090 lease
->extradata
= NULL
;
1095 return 0; /* nothing to do */
1099 void lease_add_extradata(struct dhcp_lease
*lease
, unsigned char *data
, unsigned int len
, int delim
)
1103 /* check for embeded NULLs */
1104 for (i
= 0; i
< len
; i
++)
1111 if ((lease
->extradata_size
- lease
->extradata_len
) < (len
+ 1))
1113 size_t newsz
= lease
->extradata_len
+ len
+ 100;
1114 unsigned char *new = whine_malloc(newsz
);
1119 if (lease
->extradata
)
1121 memcpy(new, lease
->extradata
, lease
->extradata_len
);
1122 free(lease
->extradata
);
1125 lease
->extradata
= new;
1126 lease
->extradata_size
= newsz
;
1130 memcpy(lease
->extradata
+ lease
->extradata_len
, data
, len
);
1131 lease
->extradata
[lease
->extradata_len
+ len
] = delim
;
1132 lease
->extradata_len
+= len
+ 1;
1138 void tomato_helper(time_t now
)
1143 struct dhcp_lease
*lease
;
1145 // if delete exists...
1146 if ((f
= fopen("/var/tmp/dhcp/delete", "r")) != NULL
) {
1147 while (fgets(buf
, sizeof(buf
), f
)) {
1148 ia
.s_addr
= inet_addr(buf
);
1149 lease
= lease_find_by_addr(ia
);
1151 lease_prune(lease
, 0);
1152 lease_update_file(now
);
1156 unlink("/var/tmp/dhcp/delete");
1159 // dump the leases file
1160 if ((f
= fopen("/var/tmp/dhcp/leases.!", "w")) != NULL
) {
1161 for (lease
= leases
; lease
; lease
= lease
->next
) {
1162 if (lease
->hwaddr_type
== ARPHRD_ETHER
) {
1163 #ifdef HAVE_DHCPV6 //only dump dhcpv6 if we have it
1164 if (lease
->flags
& (LEASE_TA
| LEASE_NA
))
1165 inet_ntop(AF_INET6
, &lease
->addr6
, buf
, ADDRSTRLEN
);
1167 #endif // Thanks to Shibby :-)
1168 inet_ntop(AF_INET
, &lease
->addr
, buf
, ADDRSTRLEN
);
1170 fprintf(f
, "%lu %02X:%02X:%02X:%02X:%02X:%02X %s %s\n",
1171 lease
->expires
- now
,
1172 lease
->hwaddr
[0], lease
->hwaddr
[1], lease
->hwaddr
[2], lease
->hwaddr
[3], lease
->hwaddr
[4], lease
->hwaddr
[5],
1174 ((lease
->hostname
) && (strlen(lease
->hostname
) > 0)) ? lease
->hostname
: "*");
1178 rename("/var/tmp/dhcp/leases.!", "/var/tmp/dhcp/leases");
1181 #endif //HAVE_TOMATO
1183 #ifdef HAVE_LEASEFILE_EXPIRE
1184 void flush_lease_file(time_t now
)
1186 static time_t flush_time
= (time_t)0;
1188 if(difftime(flush_time
, now
) < 0)
1191 lease_prune(NULL
, now
);
1192 lease_update_file(now
);
1194 if (file_dirty
== 0)
1197 #endif //HAVE_LEASEFILE_EXPIRE