Implement --dhcp-duid

This commit is contained in:
Simon Kelley
2012-03-09 17:45:10 +00:00
parent 760169fc43
commit 8b37270410
7 changed files with 60 additions and 20 deletions

View File

@@ -7,6 +7,8 @@ version 2.61
Add ra-names DHCPv6 keyword which adds AAAA records Add ra-names DHCPv6 keyword which adds AAAA records
for dual-stack hosts which get IPv6 addresses via SLAAC. for dual-stack hosts which get IPv6 addresses via SLAAC.
Add --dhcp-duid to allow DUID-EN uids to be used.
version 2.60 version 2.60
Fix compilation problem in Mac OS X Lion. Thanks to Olaf Fix compilation problem in Mac OS X Lion. Thanks to Olaf

View File

@@ -1042,6 +1042,16 @@ the tags used to determine them.
.B \-l, --dhcp-leasefile=<path> .B \-l, --dhcp-leasefile=<path>
Use the specified file to store DHCP lease information. Use the specified file to store DHCP lease information.
.TP .TP
.B --dhcp-duid=<enterprise-id>,<uid>
(IPv6 only) Specify the server persistent UID which the DHCPv6 server
will use. This option is not normally required as dnsmasq creates a
DUID automatically when it is first needed. When given, this option
provides dnsmasq the data required to create a DUID-EN type DUID. Note
that once set, the DUID is stored in the lease database, so to change between DUID-EN and
automatically created DUIDs or vice-versa, the lease database must be
re-intialised. The enterprise-id is assigned by IANA, and the uid is a
string of hex octets unique to a particular device.
.TP
.B \-6 --dhcp-script=<path> .B \-6 --dhcp-script=<path>
Whenever a new DHCP lease is created, or an old one destroyed, the Whenever a new DHCP lease is created, or an old one destroyed, the
executable specified by this option is run. <path> executable specified by this option is run. <path>

View File

@@ -365,13 +365,26 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
void make_duid(time_t now) void make_duid(time_t now)
{ {
/* rebase epoch to 1/1/2000 */ if (daemon->duid_config)
time_t newnow = now - 946684800; {
unsigned char *p;
iface_enumerate(AF_LOCAL, &newnow, make_duid1); daemon->duid = p = safe_malloc(daemon->duid_config_len + 6);
daemon->duid_len = daemon->duid_config_len + 6;
PUTSHORT(2, p); /* DUID_EN */
PUTLONG(daemon->duid_enterprise, p);
memcpy(p, daemon->duid_config, daemon->duid_config_len);
}
else
{
/* rebase epoch to 1/1/2000 */
time_t newnow = now - 946684800;
if(!daemon->duid) iface_enumerate(AF_LOCAL, &newnow, make_duid1);
die("Cannot create DHCPv6 server DUID: %s", NULL, EC_MISC);
if(!daemon->duid)
die("Cannot create DHCPv6 server DUID: %s", NULL, EC_MISC);
}
} }
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm) static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm)

View File

@@ -196,7 +196,7 @@ int main (int argc, char **argv)
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
/* after netlink_init */ /* after netlink_init */
if (daemon->dhcp || daemon->dhcp6) if (daemon->dhcp || daemon->dhcp6)
lease_find_interfaces(); lease_find_interfaces(now);
#endif #endif
if (!enumerate_interfaces()) if (!enumerate_interfaces())

View File

@@ -731,6 +731,8 @@ extern struct daemon {
struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */ struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */ struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */
int tftp_unlimited; int tftp_unlimited;
unsigned int duid_enterprise, duid_config_len;
unsigned char *duid_config;
/* globally used stuff for DNS */ /* globally used stuff for DNS */
char *packet; /* packet buffer */ char *packet; /* packet buffer */
@@ -956,7 +958,7 @@ void lease_prune(struct dhcp_lease *target, time_t now);
void lease_update_from_configs(void); void lease_update_from_configs(void);
int do_script_run(time_t now); int do_script_run(time_t now);
void rerun_scripts(void); void rerun_scripts(void);
void lease_find_interfaces(void); void lease_find_interfaces(time_t now);
#ifdef HAVE_SCRIPT #ifdef HAVE_SCRIPT
void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
unsigned int len, int delim); unsigned int len, int delim);

View File

@@ -175,16 +175,6 @@ void lease_init(time_t now)
file_dirty = 0; file_dirty = 0;
lease_prune(NULL, now); lease_prune(NULL, now);
dns_dirty = 1; dns_dirty = 1;
#ifdef HAVE_DHCP6
/* 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)
{
file_dirty = 1;
make_duid(now);
}
#endif
} }
void lease_update_from_configs(void) void lease_update_from_configs(void)
@@ -381,11 +371,18 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
we do DHCP transactions, but information about directly-connected subnets we do DHCP transactions, but information about directly-connected subnets
is useful from scrips and necessary for determining SLAAC addresses from is useful from scrips and necessary for determining SLAAC addresses from
start-time. */ start-time. */
void lease_find_interfaces(void) void lease_find_interfaces(time_t now)
{ {
iface_enumerate(AF_INET, NULL, find_interface_v4); iface_enumerate(AF_INET, NULL, find_interface_v4);
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
iface_enumerate(AF_INET6, NULL, find_interface_v6); iface_enumerate(AF_INET6, NULL, find_interface_v6);
/* 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)
{
file_dirty = 1;
make_duid(now);
}
#endif #endif
} }

View File

@@ -115,6 +115,7 @@ struct myoption {
#define LOPT_FQDN 304 #define LOPT_FQDN 304
#define LOPT_LUASCRIPT 305 #define LOPT_LUASCRIPT 305
#define LOPT_RA 306 #define LOPT_RA 306
#define LOPT_DUID 307
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
@@ -235,6 +236,7 @@ static const struct myoption opts[] =
{ "dhcp-client-update", 0, 0, LOPT_FQDN }, { "dhcp-client-update", 0, 0, LOPT_FQDN },
{ "dhcp-luascript", 1, 0, LOPT_LUASCRIPT }, { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
{ "enable-ra", 0, 0, LOPT_RA }, { "enable-ra", 0, 0, LOPT_RA },
{ "dhcp-duid", 1, 0, LOPT_DUID },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
@@ -362,6 +364,7 @@ static struct {
{ LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL }, { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
{ LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL }, { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL }, { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
@@ -3047,6 +3050,19 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
break; break;
#endif #endif
#ifdef HAVE_DHCP6
case LOPT_DUID: /* --dhcp-duid */
if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
problem = _("bad DUID");
else
{
daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
daemon->duid_config = opt_malloc(daemon->duid_config_len);
memcpy(daemon->duid_config, comma, daemon->duid_config_len);
}
break;
#endif
case 'V': /* --alias */ case 'V': /* --alias */
{ {
char *dash, *a[3] = { NULL, NULL, NULL }; char *dash, *a[3] = { NULL, NULL, NULL };