Merged rt43927.
supplying the patch.
[ISC-Bugs #29108]
+- IPv6 operation now supports an EUI-64 based address allocation which will
+ calculate addresses for clients with EUI-64 DUIDs based on those DUIDs when
+ enabled by setting use-eui-64 true. The parameter may defined down to the
+ pool scope. Note this feature must be compiled in by defining EUI_64 in
+ includes/site.h. This flag is undefined by default.
+ [ISC-Bugs #43927]
+
Changes since 4.3.0 (bug fixes)
- Tidy up several small tickets.
way... */
/*
- * Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
return htons((u_int16_t)local_port);
}
+
+#ifdef DHCPv6
+/* Print a v6 address from an in6_addr struct */
+const char *
+pin6_addr(const struct in6_addr *src){
+
+ if (!src) {
+ return ("<null>");
+ }
+
+ struct iaddr addr;
+ addr.len = 16;
+ memcpy(addr.iabuf, src->s6_addr, 16);
+ return (piaddr(addr));
+}
+#endif
#define IRT_DEFAULT 86400
#define IRT_MINIMUM 600
+#define EUI_64_ID_LEN 12 /* 2 for duid-type, 2 for hardware type, 8 for ID */
+#define IAID_LEN 4
+
Definitions for dhcpd... */
/*
- * Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
#define SV_PREFIX_LEN_MODE 87
#define SV_DHCPV6_SET_TEE_TIMES 88
#define SV_ABANDON_LEASE_TIME 89
+#ifdef EUI_64
+#define SV_USE_EUI_64 90
+#endif
#if !defined (DEFAULT_PING_TIMEOUT)
# define DEFAULT_PING_TIMEOUT 1
int logged; /* already logged a message */
isc_uint64_t low_threshold; /* low threshold to restart logging */
int jumbo_range;
+#ifdef EUI_64
+ int use_eui_64; /* use EUI-64 address assignment when true */
+#endif
};
/*
char *piaddrcidr(const struct iaddr *, unsigned int);
u_int16_t validate_port(char *);
u_int16_t validate_port_pair(char *);
+#if defined(DHCPv6)
+const char *pin6_addr (const struct in6_addr*);
+#endif
/* dhclient.c */
extern int nowait;
unsigned int *attempts,
const struct data_string *uid,
time_t soft_lifetime_end_time);
+#ifdef EUI_64
+int valid_eui_64_duid(const struct data_string* uid, int duid_beg);
+int valid_for_eui_64_pool(struct ipv6_pool*, struct data_string* uid,
+ int duid_beg, struct in6_addr* ia_addr);
+isc_result_t create_lease6_eui_64(struct ipv6_pool *pool,
+ struct iasubopt **addr,
+ const struct data_string *iaid_uid,
+ time_t soft_lifetime_end_time);
+#endif
isc_result_t add_lease6(struct ipv6_pool *pool,
struct iasubopt *lease,
time_t valid_lifetime_end_time);
allow at one time. A value of 0 means there is no limit.*/
#define MAX_FD_VALUE 200
+/* Enable EUI-64 Address assignment policy. Instructs the server
+ * to use EUI-64 addressing instead of dynamic address allocation
+ * for IA_NA pools, if the parameter use-eui-64 is true for the
+ * pool. Can be at all scopes down to the pool level. Not
+ * supported by the configure script. */
+/* #define EUI_64 */
+
/* Include definitions for various options. In general these
should be left as is, but if you have already defined one
of these and prefer your definition you can comment the
Parser for dhcpd config file... */
/*
- * Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
iasubopt_dereference(&iaaddr, MDL);
continue;
}
+#ifdef EUI_64
+ if ((pool->ipv6_pond->use_eui_64) &&
+ (!valid_for_eui_64_pool(pool, &ia->iaid_duid, IAID_LEN,
+ &iaaddr->addr))) {
+ log_error("Non EUI-64 lease in EUI-64 pool: %s"
+ " discarding it",
+ pin6_addr(&iaaddr->addr));
+ iasubopt_dereference(&iaaddr, MDL);
+ continue;
+ }
+#endif
/* remove old information */
if (cleanup_lease6(ia_na_active, pool,
.\" dhcpd.conf.5
.\"
-.\" Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
.\" Copyright (c) 1996-2003 by Internet Software Consortium
.\"
.\" Permission to use, copy, modify, and distribute this software for any
about the address.
.PP
There may be a host declaration matching the client's identification.
-If that host declaration contains a fixed-address declaration that
+If that host declaration contains a fixed-address declaration that
lists an IP address that is valid for the network segment to which the
client is connected. In this case, the DHCP server will never do
dynamic address allocation. In this case, the client is \fIrequired\fR
.PP
The statements in the peer declaration are as follows:
.PP
-The
+The
.I primary
and
.I secondary
described earlier under DHCP FAILOVER.
.RE
.PP
-The
+The
.I address
statement
.RS 0.25i
value is used as an identifier, it may not be omitted.
.RE
.PP
-The
+The
.I peer address
statement
.RS 0.25i
messages.
.RE
.PP
-The
+The
.I port
statement
.RS 0.25i
used by default.
.RE
.PP
-The
+The
.I peer port
statement
.RS 0.25i
parameter must be specified.
.RE
.PP
-The
+The
.I mclt
statement
.RS 0.25i
operational experience with this.
.RE
.PP
-The
+The
.I split
statement
.RS 0.25i
of 256 makes the primary responsible for all clients.
.RE
.PP
-The
+The
.I hba
statement
.RS 0.25i
.fi
.PP
This is equivalent to a \fBsplit 128;\fR statement, and identical. The
-following two examples are also equivalent to a \fBsplit\fR of 128, but
+following two examples are also equivalent to a \fBsplit\fR of 128, but
are not identical:
.PP
.nf
\fBsplit\fR should be used.
.RE
.PP
-The
+The
.I load balance max seconds
statement
.RS 0.25i
own updates if it chooses to do so. With \fIdeny client-updates;\fR, a
response is sent which indicates the client may not perform updates.
.PP
-Both the standard and interim options also include a method to
+Both the standard and interim options also include a method to
allow more than one DHCP server to update the DNS database without
accidentally deleting A records that shouldn\'t be deleted nor failing
to add A records that should be added. For the standard option the
records in your name server - in the above example, there must be an
SOA record for "example.org." and for "17.10.10.in-addr.arpa.". For
example, if there were a subdomain "foo.example.org" with no separate
-SOA, you could not write a zone declaration for "foo.example.org."
+SOA, you could not write a zone declaration for "foo.example.org."
Also keep in mind that zone names in your DHCP configuration should end in a
"."; this is the preferred syntax. If you do not end your zone name in a
".", the DHCP server will figure it out. Also note that in the DHCP
the contents of that file as though it were entered in place of the
include statement.
.PP
-.B The
+.B The
.I shared-network
.B statement
.PP
(although it will never be used as such), or it may be any arbitrary
name, enclosed in quotes.
.PP
-.B The
+.B The
.I subnet
.B statement
.PP
The
.I subnet-number
should be an IP address or domain name which resolves to the subnet
-number of the subnet being described. The
+number of the subnet being described. The
.I netmask
should be an IP address or domain name which resolves to the subnet mask
of the subnet being described. The subnet number, together with the
the desired subnet mask, since any subnet-mask option statement will
override the subnet mask declared in the subnet statement.
.PP
-.B The
+.B The
.I subnet6
.B statement
.PP
information to tell whether or not an IPv6 address is on that subnet6.
It may also be used to provide subnet-specific parameters and to
specify what addresses may be dynamically allocated to clients booting
-on that subnet.
+on that subnet.
.PP
The
.I subnet6-number
.PP
For any IPv6 subnet6 on which addresses will be assigned dynamically, there
must be at least one \fIrange6\fR statement. The \fIrange6\fR statement
-can either be the lowest and highest IPv6 addresses in a \fIrange6\fR, or
-use CIDR notation, specified as ip6-address/bits. All IP addresses
+can either be the lowest and highest IPv6 addresses in a \fIrange6\fR, or
+use CIDR notation, specified as ip6-address/bits. All IP addresses
in the \fIrange6\fR should be in the subnet6 in which the
\fIrange6\fR statement is declared.
.PP
network is computed at each request with an IA_TA option. Release and Confirm
ignores temporary addresses.
.PP
-Any IPv6 addresses given to hosts with \fIfixed-address6\fR are excluded
+Any IPv6 addresses given to hosts with \fIfixed-address6\fR are excluded
from the \fIrange6\fR, as are IPv6 addresses on the server itself.
.PP
.PP
statements.
.PP
If client-specific boot parameters must change based on the network
-to which the client is attached, then multiple
+to which the client is attached, then multiple
.B host
declarations should be used. The
.B host
.PP
The \fBleasequery\fR flag tells the DHCP server whether or not to
answer DHCPLEASEQUERY packets. The answer to a DHCPLEASEQUERY packet
-includes information about a specific lease, such as when it was
-issued and when it will expire. By default, the server will not
+includes information about a specific lease, such as when it was
+issued and when it will expire. By default, the server will not
respond to these packets.
.SH ALLOW AND DENY WITHIN POOL DECLARATIONS
.PP
is \fBnone\fR.
.RE
.PP
-.B The
+.B The
.I ddns-updates
.B statement
.RS 0.25i
left it disabled by default.
.RE
.PP
-The
-.I dhcp-cache-threshold
+The
+.I dhcp-cache-threshold
statement
.RS 0.25i
.PP
\fIflag\fR is false, no lookups are done.
.RE
.PP
-The
+The
.I hardware
statement
.RS 0.25i
for DHCP clients.
.RE
.PP
-The
+The
.I host-identifier option
statement
.RS 0.25i
.I host
statement.
.I option-name
-is any option, and
+is any option, and
.I option-data
-is the value for the option that the client will send. The
+is the value for the option that the client will send. The
.I option-data
must be a constant value. In the v6relopts case the additional number
is the relay to examine for the specified option name and value. The
relay closest to the server independent of number.
.RE
.PP
-The
+The
.I ignore-client-uids
statement
.RS 0.25i
If the \fIignore-client-uids\fR statement is present and has a value of
\fItrue\fR or \fIon\fR, the UID for clients will not be recorded.
If this statement is not present or has a value of \fIfalse\fR or
-\fIoff\fR, then client UIDs will be recorded.
+\fIoff\fR, then client UIDs will be recorded.
.RE
.PP
The
.PP
The
.I log-threshold-high
-and
+and
.I log-threshold-low
statements
.RS 0.25i
.I Time
should be the minimum length in seconds that will be assigned to a
lease.
-The default is the minimum of 300 seconds or
+The default is the minimum of 300 seconds or
\fBmax-lease-time\fR.
.RE
.PP
pool6 {
:
}
- # pool C
+ # pool C
pool6 {
:
}
client renews its lease, which could have a significant performance
impact in environments that place heavy demands on the DHCP server.
.RE
+
+
+.PP
+The
+.I use-eui-64
+statement
+.RS 0.25i
+.PP
+.B use-eui-64 \fIflag\fB;\fR
+.PP
+
+(Support for this must be enabled at compile time, see EUI_64 in
+ includes/site.h)
+
+The \fIuse-eui-64\fR flag, if enabled, instructs the server to construct an
+address using the client's EUI-64 DUID (Type 3, HW Type EUI-64), rather than
+creating an address using the dynamic algorithm. This means that a given DUID
+will always generate the same address for a given pool and further that the
+address is guaranteed to be unique to that DUID. The IPv6 address will be
+calculated from the EUI-64 link layer address, conforming to RFC 2373, unless
+there is a host declaration for the client-id.
+
+The range6 statement for EUI-64 must define full /64 bit ranges. Invalid ranges
+will be flagged during configuration parsing as errors. See the following
+example:
+
+ subnet6 fc00:e4::/64 {
+ use-eui-64 true;
+ range6 fc00:e4::/64;
+ }
+
+The statement may be specified down to the pool level, allowing a mixture of
+dynamic and EUI-64 based pools.
+
+During lease file parsing, any leases which map to an EUI-64 pool, that have a
+non-EUI-64 DUID or for which the lease address is not the EUI-64 address for
+that DUID in that pool, will be discarded.
+
+If a host declaration exists for the DUID, the server grants the address
+(fixed-prefix6, fixed-address6) according to the host declaration, regardless
+of the DUID type of the client (even for EUI-64 DUIDs).
+
+If a client request's an EUI-64 lease for a given network, and the resultant
+address conflicts with a fixed address reservation, the server will send the
+client a "no addresses available" response.
+
+Any client with a non-conforming DUID (not type 3 or not hw type EUI-64) that
+is not linked to a host declaration, which requests an address from an EUI-64
+enabled pool will be ignored and the event will be logged.
+
+Pools that are configured for EUI-64 will be skipped for dynamic allocation.
+If there are no pools in the shared network from which to allocate, the client
+will get back a no addresses available status.
+
+On an EUI-64 enabled pool, any client with a DUID 3, HW Type EUI-64, requesting
+a solicit/renew and including IA_NA that do not match the EUI-64 policy, they
+will be treated as though they are "outside" the subnet for a given client
+message:
+
+ Solicit - Server will advertise with EUI-64 ia suboption, but with rapid
+ commit off
+ Request - Server will send "an address not on link status", and no ia
+ suboption Renew/Rebind - Server will send the requested address ia
+ suboption with lifetimes of 0, plus an EUI-64 ia
+.RE
.PP
The
.I use-host-decl-names
.SH SETTING PARAMETER VALUES USING EXPRESSIONS
Sometimes it's helpful to be able to set the value of a DHCP server
parameter based on some value that the client has sent. To do this,
-you can use expression evaluation. The
+you can use expression evaluation. The
.B dhcp-eval(5)
manual page describes how to write expressions. To assign the result
of an evaluation to an option, define the option as follows:
It's often useful to allocate a single address to a single client, in
approximate perpetuity. Host statements with \fBfixed-address\fR clauses
exist to a certain extent to serve this purpose, but because host statements
-are intended to approximate \'static configuration\', they suffer from not
+are intended to approximate \'static configuration\', they suffer from not
being referenced in a littany of other Server Services, such as dynamic DNS,
failover, \'on events\' and so forth.
.PP
/*
- * Copyright (C) 2006-2016 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2006-2017 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
return result;
}
-
/*!
*
* \brief Get an IPv6 address for the client.
(!permitted(reply->packet, pond->permit_list))))
continue;
+#ifdef EUI_64
+ /* If pond is EUI-64 but client duid isn't a valid EUI-64
+ * id, then skip this pond */
+ if (pond->use_eui_64 &&
+ !valid_eui_64_duid(&reply->ia->iaid_duid, IAID_LEN)) {
+ continue;
+ }
+#endif
+
start_pool = pond->last_ipv6_pool;
i = start_pool;
do {
p = pond->ipv6_pools[i];
if (p->pool_type == D6O_IA_NA) {
- result = create_lease6(p, addr, &attempts,
- &reply->ia->iaid_duid,
- cur_time + 120);
+#ifdef EUI_64
+ if (pond->use_eui_64) {
+ result =
+ create_lease6_eui_64(p, addr,
+ &reply->ia->iaid_duid,
+ cur_time + 120);
+ }
+ else
+#endif
+ {
+ result =
+ create_lease6(p, addr, &attempts,
+ &reply->ia->iaid_duid,
+ cur_time + 120);
+
+ }
+
if (result == ISC_R_SUCCESS) {
/*
* Record the pool used (or next one if
struct option_cache *oc;
struct data_string iaaddr, data;
isc_result_t status = ISC_R_SUCCESS;
+#ifdef EUI_64
+ int invalid_for_eui_64 = 0;
+#endif
/* Initializes values that will be cleaned up. */
memset(&iaaddr, 0, sizeof(iaaddr));
break;
}
+#ifdef EUI_64
+ if (subnet) {
+ /* If the requested address falls into an EUI-64 pool, then
+ * we need to verify if it has EUI-64 duid AND the requested
+ * address is correct for that duid. If not we treat it just
+ * like an not-on-link request. */
+ struct ipv6_pool* pool = NULL;
+ struct in6_addr* addr = (struct in6_addr*)(iaaddr.data);
+ if ((find_ipv6_pool(&pool, D6O_IA_NA, addr) == ISC_R_SUCCESS)
+ && (pool->ipv6_pond->use_eui_64) &&
+ (!valid_for_eui_64_pool(pool, &reply->client_id, 0, addr))) {
+ log_debug ("Requested address: %s,"
+ " not valid for EUI-64 pool",
+ pin6_addr(addr));
+ invalid_for_eui_64 = 1;
+ }
+ }
+#endif
+
/* Address not found on shared network. */
+#ifdef EUI_64
+ if ((subnet == NULL) || invalid_for_eui_64) {
+#else
if (subnet == NULL) {
+#endif
/* Ignore this address on 'soft' bindings. */
if (reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
/* disable rapid commit */
goto send_addr;
}
+
/* Verify the address belongs to the client. */
if (!address_is_owned(reply, &tmp_addr)) {
/*
* Get an address in this temporary pool.
*/
status = create_lease6(p, &reply->lease, &attempts,
- &reply->client_id, cur_time + 120);
+ &reply->client_id,
+ cur_time + 120);
+
if (status != ISC_R_SUCCESS) {
log_debug("Unable to get a temporary address.");
goto cleanup;
/*
- * Copyright (C) 2007-2016 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2007-2017 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
str[8] &= ~0x02;
}
+#ifdef EUI_64
+int
+valid_eui_64_duid(const struct data_string* uid, int offset) {
+ if (uid->len == (offset + EUI_64_ID_LEN)) {
+ const unsigned char* duid = uid->data + offset;
+ return (((duid[0] == 0x00 && duid[1] == 0x03) &&
+ (duid[2] == 0x00 && duid[3] == 0x1b)));
+ }
+
+ return(0);
+}
+
+
+/*
+ * Create an EUI-64 address
+ */
+static isc_result_t
+build_address6_eui_64(struct in6_addr *addr,
+ const struct in6_addr *net_start_addr, int net_bits,
+ const struct data_string *iaid_duid, int duid_beg) {
+
+ if (net_bits != 64) {
+ log_error("build_address_eui_64: network is not 64 bits");
+ return (ISC_R_FAILURE);
+ }
+
+ if (valid_eui_64_duid(iaid_duid, duid_beg)) {
+ const unsigned char *duid = iaid_duid->data + duid_beg;
+
+ /* copy network prefix to the high 64 bits */
+ memcpy(addr->s6_addr, net_start_addr->s6_addr, 8);
+
+ /* copy Link-layer address to low 64 bits */
+ memcpy(addr->s6_addr + 8, duid + 4, 8);
+
+ /* RFC-3315 Any address assigned by a server that is based
+ * on an EUI-64 identifier MUST include an interface identifier
+ * with the "u" (universal/local) and "g" (individual/group)
+ * bits of the interface identifier set appropriately, as
+ * indicated in section 2.5.1 of RFC 2373 [5]. */
+ addr->s6_addr[8] |= 0x02;
+ return (ISC_R_SUCCESS);
+ }
+
+ log_error("build_address_eui_64: iaid_duid not a valid EUI-64: %s",
+ print_hex_1(iaid_duid->len, iaid_duid->data, 60));
+ return (ISC_R_FAILURE);
+}
+
+int
+valid_for_eui_64_pool(struct ipv6_pool* pool, struct data_string* uid,
+ int duid_beg, struct in6_addr* ia_addr) {
+ struct in6_addr test_addr;
+ /* If it's not an EUI-64 pool bail */
+ if (!pool->ipv6_pond->use_eui_64) {
+ return (0);
+ }
+
+ if (!valid_eui_64_duid(uid, duid_beg)) {
+ /* Dynamic lease in a now eui_64 pond, toss it*/
+ return (0);
+ }
+
+ /* Call build_address6_eui_64() and compare it's result to
+ * this lease and see if they match. */
+ memset (&test_addr, 0, sizeof(test_addr));
+ build_address6_eui_64(&test_addr, &pool->start_addr, pool->bits,
+ uid, duid_beg);
+
+ return (!memcmp(ia_addr, &test_addr, sizeof(test_addr)));
+}
+#endif
+
+
/*
* Create a temporary address by a variant of RFC 4941 algo.
* Note: this should not be used for prefixes shorter than 64 bits.
return result;
}
+#ifdef EUI_64
+/*!
+ * \brief Assign an EUI-64 address from a pool for a given iaid-duid
+ *
+ * \param pool - pool from which the address is assigned
+ * \param iaddr - pointer to the iasubopt to contain the assigned address is
+ * \param uid - data_string containing the iaid-duid tuple
+ * \param soft_lifetime_end_time - lifetime of the lease for a solicit?
+ *
+ * \return status indicating success or nature of the failure
+*/
+isc_result_t
+create_lease6_eui_64(struct ipv6_pool *pool, struct iasubopt **addr,
+ const struct data_string *uid,
+ time_t soft_lifetime_end_time) {
+ struct in6_addr tmp;
+ struct iasubopt *test_iaaddr;
+ struct iasubopt *iaaddr;
+ isc_result_t result;
+ static isc_boolean_t init_resiid = ISC_FALSE;
+
+ /* Fill the reserved IIDs. */
+ if (!init_resiid) {
+ memset(&rtany, 0, 16);
+ memset(&resany, 0, 8);
+ resany.s6_addr[8] = 0xfd;
+ memset(&resany.s6_addr[9], 0xff, 6);
+ init_resiid = ISC_TRUE;
+ }
+
+ /* Pool must be IA_NA */
+ if (pool->pool_type != D6O_IA_NA) {
+ log_error("create_lease6_eui_64: pool type is not IA_NA.");
+ return (DHCP_R_INVALIDARG);
+ }
+
+ /* Attempt to build the address */
+ if (build_address6_eui_64 (&tmp, &pool->start_addr, pool->bits,
+ uid, IAID_LEN) != ISC_R_SUCCESS) {
+ log_error("create_lease6_eui_64: build_address6_eui_64 failed");
+ return (ISC_R_FAILURE);
+ }
+
+ /* Avoid reserved interface IDs. (cf. RFC 5453) */
+ if ((memcmp(&tmp.s6_addr[8], &rtany.s6_addr[8], 8) == 0) ||
+ ((memcmp(&tmp.s6_addr[8], &resany.s6_addr[8], 7) == 0) &&
+ ((tmp.s6_addr[15] & 0x80) == 0x80))) {
+ log_error("create_lease6_eui_64: "
+ "address conflicts with reserved IID");
+ return (ISC_R_FAILURE);
+ }
+
+ /* If this address is not in use, we're happy with it */
+ test_iaaddr = NULL;
+ if (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
+ &tmp, sizeof(tmp), MDL) != 0) {
+
+ /* See if it's ours. Static leases won't have an ia */
+ int ours = 0;
+ if (!test_iaaddr->ia) {
+ log_error("create_lease6_eui_64: "
+ "address %s is assigned to static lease",
+ pin6_addr(&test_iaaddr->addr));
+ } else {
+ /* Not sure if this can actually happen */
+ struct data_string* found = &test_iaaddr->ia->iaid_duid;
+ ours = ((found->len == uid->len) &&
+ (!memcmp(found->data, uid->data, uid->len)));
+ log_error("create_lease6_eui_64: "
+ "address %s belongs to %s",
+ pin6_addr(&test_iaaddr->addr),
+ print_hex_1(found->len, found->data, 60));
+ }
+
+ iasubopt_dereference(&test_iaaddr, MDL);
+ if (!ours) {
+ /* Cant' use it */
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ /* We're happy with the address, create an IAADDR to hold it. */
+ iaaddr = NULL;
+ result = iasubopt_allocate(&iaaddr, MDL);
+ if (result != ISC_R_SUCCESS) {
+ log_error("create_lease6_eui_64: could not allocate iasubop");
+ return result;
+ }
+ iaaddr->plen = 0;
+ memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
+
+ /* Add the lease to the pool and the reply */
+ result = add_lease6(pool, iaaddr, soft_lifetime_end_time);
+ if (result == ISC_R_SUCCESS) {
+ iasubopt_reference(addr, iaaddr, MDL);
+ }
+
+ iasubopt_dereference(&iaaddr, MDL);
+ return result;
+}
+#endif
/*!
*
return ISC_R_SUCCESS;
}
+#ifdef EUI_64
+/*
+ * Enables/disables EUI-64 address assignment for a pond
+ *
+ * Excecutes statements down to the pond's scope and sets the pond's
+ * use_eui_64 flag accordingly. In addition it iterates over the
+ * pond's pools ensuring they are all /64. Anything else is deemed
+ * invalid for EUI-64. It returns the number of invalid pools
+ * detected. This is done post-parsing as use-eui-64 can be set
+ * down to the pool scope and we can't reliably do it until the
+ * entire configuration has been parsed.
+ */
+int
+set_eui_64(struct ipv6_pond *pond) {
+ int invalid_cnt = 0;
+ struct option_state* options = NULL;
+ struct option_cache *oc = NULL;
+ option_state_allocate(&options, MDL);
+ execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL, options,
+ &global_scope, pond->group, NULL, NULL);
+
+ pond->use_eui_64 =
+ ((oc = lookup_option(&server_universe, options, SV_USE_EUI_64))
+ &&
+ (evaluate_boolean_option_cache (NULL, NULL, NULL, NULL,
+ options, NULL, &global_scope,
+ oc, MDL)));
+ if (pond->use_eui_64) {
+ // Check all pools are valid
+ int i = 0;
+ struct ipv6_pool* p;
+ while((p = pond->ipv6_pools[i++]) != NULL) {
+ if (p->bits != 64) {
+ log_error("Pool %s/%d cannot use EUI-64,"
+ " prefix must 64",
+ pin6_addr(&p->start_addr), p->bits);
+ invalid_cnt++;
+ } else {
+ log_debug("Pool: %s/%d - will use EUI-64",
+ pin6_addr(&p->start_addr), p->bits);
+ }
+ }
+ }
+
+ /* Don't need the options anymore. */
+ option_state_dereference(&options, MDL);
+ return (invalid_cnt);
+}
+#endif
+
/*
* Emits a log for each pond that has been flagged as being a "jumbo range"
* A pond is considered a "jumbo range" when the total number of elements
report_jumbo_ranges() {
struct shared_network* s;
char log_buf[1084];
+#ifdef EUI_64
+ int invalid_cnt = 0;
+#endif
/* Loop thru all the networks looking for jumbo range ponds */
for (s = shared_networks; s; s = s -> next) {
struct ipv6_pond* pond = s->ipv6_pond;
while (pond) {
+#ifdef EUI_64
+ /* while we're here, set the pond's use_eui_64 flag */
+ invalid_cnt += set_eui_64(pond);
+#endif
/* if its a jumbo and has pools(sanity check) */
if (pond->jumbo_range == 1 && (pond->ipv6_pools)) {
struct ipv6_pool* pool;
}
pond = pond->next;
}
+
+ }
+
+#ifdef EUI_64
+ if (invalid_cnt) {
+ log_fatal ("%d pool(s) are invalid for EUI-64 use",
+ invalid_cnt);
}
+#endif
}
|| find_hosts_by_duid_chaddr(host, client_id));
}
-
/* unittest moved to server/tests/mdb6_unittest.c */
{ "prefix-length-mode", "Nprefix_length_modes.", &server_universe, SV_PREFIX_LEN_MODE, 1 },
{ "dhcpv6-set-tee-times", "f", &server_universe, SV_DHCPV6_SET_TEE_TIMES, 1 },
{ "abandon-lease-time", "T", &server_universe, SV_ABANDON_LEASE_TIME, 1 },
+#ifdef EUI_64
+ { "use-eui-64", "f", &server_universe, SV_USE_EUI_64, 1 },
+#endif
{ NULL, NULL, NULL, 0, 0 }
};