Marius Tomaschewski
348f524f0a
reorder config to add all global options or option declarations to the dhcpService object instead to create new service object (bsc#886094,ISC-Bugs#37876). [+ dhcp-4.2.x-contrib-conf-to-ldap-reorder.886094.patch] - Applied an upstream patch by Thomas Markwalder adding missed mapping of SHA TSIG algorithm names to their constants to enable hmac-sha1, hmac_sha224, hmac_sha256, hmac_sha384 and hmac_sha512 authenticated dynamic DNS updates (bsc#890731, ISC-Bugs#36947). [+ dhcp-4.2.x-ddns-tsig-hmac-sha-support.890731.patch] - Decline IPv6 addresses on Duplicate Address Detection failure and stop client message exchanges on reached MRD rather than at some point after it. Applied fedora patches by Jiri Popelka and added DAD reporting via exit 3 to the dhclient-script and a fix to use correct address variables in the DEPREF6 action (bsc#872609,ISC-Bugs#26735,ISC-Bugs#21238). [+ dhcp-4.2.x-dhcpv6-decline-on-DAD-failure.872609.patch, + dhcp-4.2.x-dhcpv6-retransmission-until-MRD.872609.patch] - Applied backport patch by William Preston avoiding to bind ddns socket in the server when ddns-update-style is none (bsc#891655). [+ dhcp-4.2.x-disable-unused-ddns-port-in-server.891655.patch] - Applied patch for the contrib/ldap/dhcpd-conf-to-ldap script fixing subclass statement handling (bnc#878846,[ISC-Bugs #36409]) [+ dhcp-4.2.4-P2-bnc878846-conf-to-ldap.patch] - Updated licence statement and FSF address in our scripts. - Added missed service_add_pre macro calls for dhcrelay services OBS-URL: https://build.opensuse.org/package/show/network:dhcp/dhcp?expand=0&rev=141
256 lines
7.1 KiB
Diff
256 lines
7.1 KiB
Diff
Author: Jiri Popelka <jpopelka@redhat.com>
|
|
References: bsc#872609, ISC-Bugs#21237
|
|
Upstream: yes
|
|
|
|
If the bound address failed DAD (is found to be in use on the link),
|
|
the dhcpv6 client sends a Decline message to the server as described
|
|
in section 18.1.7 of RFC-3315 (#559147)
|
|
(Submitted to dhcp-bugs@isc.org - [ISC-Bugs #26735])
|
|
|
|
diff --git a/client/dhc6.c b/client/dhc6.c
|
|
index 8974e7a..f8ad25d 100644
|
|
--- a/client/dhc6.c
|
|
+++ b/client/dhc6.c
|
|
@@ -96,6 +96,8 @@ void do_select6(void *input);
|
|
void do_refresh6(void *input);
|
|
static void do_release6(void *input);
|
|
static void start_bound(struct client_state *client);
|
|
+static void start_decline6(struct client_state *client);
|
|
+static void do_decline6(void *input);
|
|
static void start_informed(struct client_state *client);
|
|
void informed_handler(struct packet *packet, struct client_state *client);
|
|
void bound_handler(struct packet *packet, struct client_state *client);
|
|
@@ -2080,6 +2082,7 @@ start_release6(struct client_state *client)
|
|
cancel_timeout(do_select6, client);
|
|
cancel_timeout(do_refresh6, client);
|
|
cancel_timeout(do_release6, client);
|
|
+ cancel_timeout(do_decline6, client);
|
|
client->state = S_STOPPED;
|
|
|
|
/*
|
|
@@ -2713,6 +2716,7 @@ dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
|
|
break;
|
|
|
|
case S_STOPPED:
|
|
+ case S_DECLINED:
|
|
action = dhc6_stop_action;
|
|
break;
|
|
|
|
@@ -2814,6 +2818,7 @@ dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
|
|
break;
|
|
|
|
case S_STOPPED:
|
|
+ case S_DECLINED:
|
|
/* Nothing critical to do at this stage. */
|
|
break;
|
|
|
|
@@ -3804,17 +3809,23 @@ reply_handler(struct packet *packet, struct client_state *client)
|
|
cancel_timeout(do_select6, client);
|
|
cancel_timeout(do_refresh6, client);
|
|
cancel_timeout(do_release6, client);
|
|
+ cancel_timeout(do_decline6, client);
|
|
|
|
/* If this is in response to a Release/Decline, clean up and return. */
|
|
- if (client->state == S_STOPPED) {
|
|
- if (client->active_lease == NULL)
|
|
- return;
|
|
+ if ((client->state == S_STOPPED) ||
|
|
+ (client->state == S_DECLINED)) {
|
|
+
|
|
+ if (client->active_lease != NULL) {
|
|
+ dhc6_lease_destroy(&client->active_lease, MDL);
|
|
+ client->active_lease = NULL;
|
|
+ /* We should never wait for nothing!? */
|
|
+ if (stopping_finished())
|
|
+ exit(0);
|
|
+ }
|
|
+
|
|
+ if (client->state == S_DECLINED)
|
|
+ start_init6(client);
|
|
|
|
- dhc6_lease_destroy(&client->active_lease, MDL);
|
|
- client->active_lease = NULL;
|
|
- /* We should never wait for nothing!? */
|
|
- if (stopping_finished())
|
|
- exit(0);
|
|
return;
|
|
}
|
|
|
|
@@ -4342,7 +4353,11 @@ start_bound(struct client_state *client)
|
|
dhc6_marshall_values("new_", client, lease, ia, addr);
|
|
script_write_requested6(client);
|
|
|
|
- script_go(client);
|
|
+ // when script returns 3, DAD failed
|
|
+ if (script_go(client) == 3) {
|
|
+ start_decline6(client);
|
|
+ return;
|
|
+ }
|
|
}
|
|
|
|
/* XXX: maybe we should loop on the old values instead? */
|
|
@@ -4390,6 +4405,149 @@ start_bound(struct client_state *client)
|
|
dhc6_check_times(client);
|
|
}
|
|
|
|
+/*
|
|
+ * Decline addresses.
|
|
+ */
|
|
+void
|
|
+start_decline6(struct client_state *client)
|
|
+{
|
|
+ /* Cancel any pending transmissions */
|
|
+ cancel_timeout(do_confirm6, client);
|
|
+ cancel_timeout(do_select6, client);
|
|
+ cancel_timeout(do_refresh6, client);
|
|
+ cancel_timeout(do_release6, client);
|
|
+ cancel_timeout(do_decline6, client);
|
|
+ client->state = S_DECLINED;
|
|
+
|
|
+ if (client->active_lease == NULL)
|
|
+ return;
|
|
+
|
|
+ /* Set timers per RFC3315 section 18.1.7. */
|
|
+ client->IRT = DEC_TIMEOUT * 100;
|
|
+ client->MRT = 0;
|
|
+ client->MRC = DEC_MAX_RC;
|
|
+ client->MRD = 0;
|
|
+
|
|
+ dhc6_retrans_init(client);
|
|
+ client->v6_handler = reply_handler;
|
|
+
|
|
+ client->refresh_type = DHCPV6_DECLINE;
|
|
+ do_decline6(client);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * do_decline6() creates a Decline packet and transmits it.
|
|
+ */
|
|
+static void
|
|
+do_decline6(void *input)
|
|
+{
|
|
+ struct client_state *client;
|
|
+ struct data_string ds;
|
|
+ int send_ret;
|
|
+ struct timeval elapsed, tv;
|
|
+
|
|
+ client = input;
|
|
+
|
|
+ if ((client->active_lease == NULL) || !active_prefix(client))
|
|
+ return;
|
|
+
|
|
+ if ((client->MRC != 0) && (client->txcount > client->MRC)) {
|
|
+ log_info("Max retransmission count exceeded.");
|
|
+ goto decline_done;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Start_time starts at the first transmission.
|
|
+ */
|
|
+ if (client->txcount == 0) {
|
|
+ client->start_time.tv_sec = cur_tv.tv_sec;
|
|
+ client->start_time.tv_usec = cur_tv.tv_usec;
|
|
+ }
|
|
+
|
|
+ /* elapsed = cur - start */
|
|
+ elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
|
|
+ elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
|
|
+ if (elapsed.tv_usec < 0) {
|
|
+ elapsed.tv_sec -= 1;
|
|
+ elapsed.tv_usec += 1000000;
|
|
+ }
|
|
+
|
|
+ memset(&ds, 0, sizeof(ds));
|
|
+ if (!buffer_allocate(&ds.buffer, 4, MDL)) {
|
|
+ log_error("Unable to allocate memory for Decline.");
|
|
+ goto decline_done;
|
|
+ }
|
|
+
|
|
+ ds.data = ds.buffer->data;
|
|
+ ds.len = 4;
|
|
+ ds.buffer->data[0] = DHCPV6_DECLINE;
|
|
+ memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
|
|
+
|
|
+ /* Form an elapsed option. */
|
|
+ /* Maximum value is 65535 1/100s coded as 0xffff. */
|
|
+ if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
|
|
+ ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
|
|
+ client->elapsed = 0xffff;
|
|
+ } else {
|
|
+ client->elapsed = elapsed.tv_sec * 100;
|
|
+ client->elapsed += elapsed.tv_usec / 10000;
|
|
+ }
|
|
+
|
|
+ client->elapsed = htons(client->elapsed);
|
|
+
|
|
+ log_debug("XMT: Forming Decline.");
|
|
+ make_client6_options(client, &client->sent_options,
|
|
+ client->active_lease, DHCPV6_DECLINE);
|
|
+ dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
|
|
+ client->sent_options, &global_scope,
|
|
+ &dhcpv6_universe);
|
|
+
|
|
+ /* Append IA's (but don't release temporary addresses). */
|
|
+ if (wanted_ia_na &&
|
|
+ dhc6_add_ia_na(client, &ds, client->active_lease,
|
|
+ DHCPV6_DECLINE) != ISC_R_SUCCESS) {
|
|
+ data_string_forget(&ds, MDL);
|
|
+ goto decline_done;
|
|
+ }
|
|
+ if (wanted_ia_pd &&
|
|
+ dhc6_add_ia_pd(client, &ds, client->active_lease,
|
|
+ DHCPV6_DECLINE) != ISC_R_SUCCESS) {
|
|
+ data_string_forget(&ds, MDL);
|
|
+ goto decline_done;
|
|
+ }
|
|
+
|
|
+ /* Transmit and wait. */
|
|
+ log_info("XMT: Decline on %s, interval %ld0ms.",
|
|
+ client->name ? client->name : client->interface->name,
|
|
+ (long int)client->RT);
|
|
+
|
|
+ send_ret = send_packet6(client->interface, ds.data, ds.len,
|
|
+ &DHCPv6DestAddr);
|
|
+ if (send_ret != ds.len) {
|
|
+ log_error("dhc6: sendpacket6() sent %d of %d bytes",
|
|
+ send_ret, ds.len);
|
|
+ }
|
|
+
|
|
+ data_string_forget(&ds, MDL);
|
|
+
|
|
+ /* Wait RT */
|
|
+ tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
|
|
+ tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
|
|
+ if (tv.tv_usec >= 1000000) {
|
|
+ tv.tv_sec += 1;
|
|
+ tv.tv_usec -= 1000000;
|
|
+ }
|
|
+ add_timeout(&tv, do_decline6, client, NULL, NULL);
|
|
+ dhc6_retrans_advance(client);
|
|
+ return;
|
|
+
|
|
+decline_done:
|
|
+ dhc6_lease_destroy(&client->active_lease, MDL);
|
|
+ client->active_lease = NULL;
|
|
+ start_init6(client);
|
|
+ return;
|
|
+}
|
|
+
|
|
/* While bound, ignore packets. In the future we'll want to answer
|
|
* Reconfigure-Request messages and the like.
|
|
*/
|
|
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
|
|
index a52992b..0eda51d 100644
|
|
--- a/includes/dhcpd.h
|
|
+++ b/includes/dhcpd.h
|
|
@@ -1060,7 +1060,8 @@ enum dhcp_state {
|
|
S_BOUND = 5,
|
|
S_RENEWING = 6,
|
|
S_REBINDING = 7,
|
|
- S_STOPPED = 8
|
|
+ S_STOPPED = 8,
|
|
+ S_DECLINED = 9
|
|
};
|
|
|
|
/* Authentication and BOOTP policy possibilities (not all values work
|