SHA256
1
0
forked from pool/dhcp
dhcp/0013-dhcp-4.2.x-dhcpv6-decline-on-DAD-failure.872609.patch
Nirmoy Das 853382bddd Accepting request 508601 from home:ndas:branches:network:dhcp
- fixed a typo in nis-servers option name breaking the config file introduced 
  in previous change to workaround issues in NetworkManager parser.
- Update to dhcp-4.3.5
  - Corrected a bug which could cause the server to sporadically crash while
    loading lease files with the lease-id-format is set to "hex".  Our thanks
    to Jay Ford, University of Iowa for reporting the issue.
    [ISC-Bugs #43185]
  - Eliminated a noisy, but otherwise harmless debug log statment that may
    appear during server startup when building with --enable-binary-leases
    and configuring multiple pools in a shared network.  Thanks to Fernando
    Soto from BlueCat Networks for reporting the issue and supplying a patch.
    [ISC-Bugs #43262]
  - Fixed util/bindvar.sh error handling.
    [ISC-Bugs #41973]
  - Correct error message in relay to use remote id length instead
    of circuit id length.
    [ISC-Bugs #42556]
  - Add logic to test directory Makefiles to avoid copying Attfile(s)
    when building within the source tree.  This eliminates a noisy but
    otherwise harmless error message when running "make check".
    [ISC-Bugs #41883]
  - Leases are now scrubbed of certain prior use information when pool
    re-balancing reassigns them from one FO peer to the other.  This
    corrects an issue where leases that were offered but not used
    by the client retained the client hostname from the original
    client. Thanks to Pavel Polacek, Jan Evangelista Purkyne University
    for reporting the issue.
    [ISC-Bugs #42008]
  - In the LDAP code and schema add some missing '6' characters to use
    the v6 instead of the v4 versions.  Thanks to Denis Taranushin for

OBS-URL: https://build.opensuse.org/request/show/508601
OBS-URL: https://build.opensuse.org/package/show/network:dhcp/dhcp?expand=0&rev=174
2017-07-06 15:49:46 +00:00

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 c8d16e8..21d0203 100644
--- a/client/dhc6.c
+++ b/client/dhc6.c
@@ -115,6 +115,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);
@@ -2314,6 +2316,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;
/*
@@ -2968,6 +2971,7 @@ dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
break;
case S_STOPPED:
+ case S_DECLINED:
action = dhc6_stop_action;
break;
@@ -3084,6 +3088,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;
@@ -4214,17 +4219,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;
}
@@ -4798,7 +4809,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? */
@@ -4851,6 +4866,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, added;
+ 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, 0, &added) != 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, 0, &added) != 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 b5bec1c..6d500a3 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -1176,7 +1176,8 @@ enum dhcp_state {
S_BOUND = 5,
S_RENEWING = 6,
S_REBINDING = 7,
- S_STOPPED = 8
+ S_STOPPED = 8,
+ S_DECLINED = 9
};
/* Possible pending client operations. */