From 3511a928691cda102d4cb395309ba46ae5920be8 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 7 Nov 2013 10:28:11 +0000 Subject: [PATCH] Fix start-up order for making DHCPv6 DUID Previously, if the DUID wasn't read from the lease-file or script, a new one was created _after_ the helper process fork, so for that first run, the script calls got an empty DUID. Also, use a DUID_LL format DUID when there's no stable lease storage, as well as when the RTC is broken. That has a chance of evaluating to the same value on each startup. --- src/dhcp6.c | 42 +++++++++++++++++++++++++++--------------- src/dnsmasq.c | 3 +++ src/dnsmasq.h | 1 + src/lease.c | 10 ++++++++-- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/dhcp6.c b/src/dhcp6.c index 7b0adcf..7c72872 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -523,6 +523,8 @@ int config_valid(struct dhcp_config *config, struct dhcp_context *context, struc void make_duid(time_t now) { + (void)now; + if (daemon->duid_config) { unsigned char *p; @@ -535,8 +537,14 @@ void make_duid(time_t now) } else { + time_t newnow = 0; + + /* If we have no persistent lease database, or a non-stable RTC, use DUID_LL (newnow == 0) */ +#ifndef HAVE_BROKEN_RTC /* rebase epoch to 1/1/2000 */ - time_t newnow = now - 946684800; + if (!option_bool(OPT_LEASE_RO) || daemon->lease_change_command) + newnow = now - 946684800; +#endif iface_enumerate(AF_LOCAL, &newnow, make_duid1); @@ -555,23 +563,27 @@ static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, vo unsigned char *p; (void)index; (void)parm; - + time_t newnow = *((time_t *)parm); + if (type >= 256) return 1; -#ifdef HAVE_BROKEN_RTC - daemon->duid = p = safe_malloc(maclen + 4); - daemon->duid_len = maclen + 4; - PUTSHORT(3, p); /* DUID_LL */ - PUTSHORT(type, p); /* address type */ -#else - daemon->duid = p = safe_malloc(maclen + 8); - daemon->duid_len = maclen + 8; - PUTSHORT(1, p); /* DUID_LLT */ - PUTSHORT(type, p); /* address type */ - PUTLONG(*((time_t *)parm), p); /* time */ -#endif - + if (newnow == 0) + { + daemon->duid = p = safe_malloc(maclen + 4); + daemon->duid_len = maclen + 4; + PUTSHORT(3, p); /* DUID_LL */ + PUTSHORT(type, p); /* address type */ + } + else + { + daemon->duid = p = safe_malloc(maclen + 8); + daemon->duid_len = maclen + 8; + PUTSHORT(1, p); /* DUID_LLT */ + PUTSHORT(type, p); /* address type */ + PUTLONG(*((time_t *)parm), p); /* time */ + } + memcpy(p, mac, maclen); return 0; diff --git a/src/dnsmasq.c b/src/dnsmasq.c index a2b37dc..a701ab5 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -273,6 +273,9 @@ int main (int argc, char **argv) /* after enumerate_interfaces() */ if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra) join_multicast(1); + + /* After netlink_init() and before create_helper() */ + lease_make_duid(now); #endif if (daemon->port != 0) diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 4d368c5..62b1d68 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1120,6 +1120,7 @@ u64 lease_find_max_addr6(struct dhcp_context *context); void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface); void lease_update_slaac(time_t now); void lease_set_iaid(struct dhcp_lease *lease, int iaid); +void lease_make_duid(time_t now); #endif void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr, unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force); diff --git a/src/lease.c b/src/lease.c index 4b4d10a..7e00804 100644 --- a/src/lease.c +++ b/src/lease.c @@ -417,15 +417,21 @@ void lease_find_interfaces(time_t now) iface_enumerate(AF_INET, &now, find_interface_v4); #ifdef HAVE_DHCP6 iface_enumerate(AF_INET6, &now, find_interface_v6); +#endif +} +#ifdef HAVE_DHCP6 +void lease_make_duid(time_t now) +{ /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */ - if (!daemon->duid && daemon->dhcp6) + if (!daemon->duid && daemon->doing_dhcp6) { file_dirty = 1; make_duid(now); } -#endif } +#endif +