diff --git a/RELNOTES b/RELNOTES index bc1a8250..230d2750 100644 --- a/RELNOTES +++ b/RELNOTES @@ -96,6 +96,10 @@ work on other platforms. Please report any problems and suggested fixes to - When parsing a domain name free the memory for the name after we are done with it. [ISC-Bugs #20824] +- Add an elapsed time option to the release message and refactor the + code to move most of the common code to a single routine. + [ISC-Bugs #21171]. + Changes since 4.2.0b2 - Add declaration for variable in debug code in alloc.c. [ISC-Bugs #21472] diff --git a/client/dhc6.c b/client/dhc6.c index cafe1221..633f9b1a 100644 --- a/client/dhc6.c +++ b/client/dhc6.c @@ -1,7 +1,7 @@ /* dhc6.c - DHCPv6 client routines. */ /* - * Copyright (c) 2006-2009 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2006-2010 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 @@ -110,6 +110,10 @@ static void script_write_params6(struct client_state *client, struct option_state *options); static isc_boolean_t active_prefix(struct client_state *client); +static int check_timing6(struct client_state *client, u_int8_t msg_type, + char *msg_str, struct dhc6_lease *lease, + struct data_string *ds); + extern int onetry; extern int stateless; @@ -1455,6 +1459,81 @@ start_confirm6(struct client_state *client) add_timeout(&tv, do_confirm6, client, NULL, NULL); } +/* + * check_timing6() check on the timing for sending a v6 message + * and then do the basic initialization for a v6 message. + */ +#define CHK_TIM_SUCCESS 0 +#define CHK_TIM_MRC_EXCEEDED 1 +#define CHK_TIM_MRD_EXCEEDED 2 +#define CHK_TIM_ALLOC_FAILURE 3 + +int +check_timing6 (struct client_state *client, u_int8_t msg_type, + char *msg_str, struct dhc6_lease *lease, + struct data_string *ds) +{ + struct timeval elapsed; + + /* + * 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; + } else if ((client->MRC != 0) && (client->txcount > client->MRC)) { + log_info("Max retransmission count exceeded."); + return(CHK_TIM_MRC_EXCEEDED); + } + + /* 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; + } + + /* Check if finished (-1 argument). */ + if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) { + log_info("Max retransmission duration exceeded."); + return(CHK_TIM_MRD_EXCEEDED); + } + + memset(ds, 0, sizeof(*ds)); + if (!buffer_allocate(&(ds->buffer), 4, MDL)) { + log_error("Unable to allocate memory for %s.", msg_str); + return(CHK_TIM_ALLOC_FAILURE); + } + ds->data = ds->buffer->data; + ds->len = 4; + + ds->buffer->data[0] = msg_type; + 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; + } + + if (client->elapsed == 0) + log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str); + else + log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str, + (unsigned)client->elapsed); + + client->elapsed = htons(client->elapsed); + + make_client6_options(client, &client->sent_options, lease, msg_type); + + return(CHK_TIM_SUCCESS); +} + /* * do_init6() marshals and transmits a solicit. */ @@ -1467,7 +1546,7 @@ do_init6(void *input) struct data_string ds; struct data_string ia; struct data_string addr; - struct timeval elapsed, tv; + struct timeval tv; u_int32_t t1, t2; int i, idx, len, send_ret; @@ -1482,29 +1561,11 @@ do_init6(void *input) return; } - if ((client->MRC != 0) && (client->txcount > client->MRC)) { - log_info("Max retransmission count exceeded."); + switch(check_timing6(client, DHCPV6_SOLICIT, "Solicit", NULL, &ds)) { + case CHK_TIM_MRC_EXCEEDED: + case CHK_TIM_ALLOC_FAILURE: return; - } - - /* - * 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; - } - /* Check if finished (-1 argument). */ - if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) { - log_info("Max retransmission duration exceeded."); + case CHK_TIM_MRD_EXCEEDED: client->state = S_STOPPED; if (client->active_lease != NULL) { dhc6_lease_destroy(&client->active_lease, MDL); @@ -1516,38 +1577,6 @@ do_init6(void *input) return; } - memset(&ds, 0, sizeof(ds)); - if (!buffer_allocate(&ds.buffer, 4, MDL)) { - log_error("Unable to allocate memory for SOLICIT."); - return; - } - ds.data = ds.buffer->data; - ds.len = 4; - - ds.buffer->data[0] = DHCPV6_SOLICIT; - 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; - } - - if (client->elapsed == 0) - log_debug("XMT: Forming Solicit, 0 ms elapsed."); - else - log_debug("XMT: Forming Solicit, %u0 ms elapsed.", - (unsigned)client->elapsed); - - client->elapsed = htons(client->elapsed); - - make_client6_options(client, &client->sent_options, NULL, - DHCPV6_SOLICIT); - /* * Fetch any configured 'sent' options (includes DUID) in wire format. */ @@ -1897,69 +1926,22 @@ do_info_request6(void *input) { struct client_state *client; struct data_string ds; - struct timeval elapsed, tv; + struct timeval tv; int send_ret; client = input; - if ((client->MRC != 0) && (client->txcount > client->MRC)) { - log_info("Max retransmission count exceeded."); + switch(check_timing6(client, DHCPV6_INFORMATION_REQUEST, + "Info-Request", NULL, &ds)) { + case CHK_TIM_MRC_EXCEEDED: + case CHK_TIM_ALLOC_FAILURE: return; - } - - /* - * 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; - } - /* Check if finished (-1 argument). */ - if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) { - log_info("Max retransmission duration exceeded."); + case CHK_TIM_MRD_EXCEEDED: exit(2); + case CHK_TIM_SUCCESS: + break; } - memset(&ds, 0, sizeof(ds)); - if (!buffer_allocate(&ds.buffer, 4, MDL)) { - log_error("Unable to allocate memory for INFO-REQUEST."); - return; - } - ds.data = ds.buffer->data; - ds.len = 4; - - ds.buffer->data[0] = DHCPV6_INFORMATION_REQUEST; - 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; - } - - if (client->elapsed == 0) - log_debug("XMT: Forming Info-Request, 0 ms elapsed."); - else - log_debug("XMT: Forming Info-Request, %u0 ms elapsed.", - (unsigned)client->elapsed); - - client->elapsed = htons(client->elapsed); - - make_client6_options(client, &client->sent_options, NULL, - DHCPV6_INFORMATION_REQUEST); - /* Fetch any configured 'sent' options (includes DUID) in wire format. */ dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, @@ -2002,7 +1984,7 @@ do_confirm6(void *input) struct client_state *client; struct data_string ds; int send_ret; - struct timeval elapsed, tv; + struct timeval tv; client = input; @@ -2023,65 +2005,18 @@ do_confirm6(void *input) * stick there until we get a reply? */ - if ((client->MRC != 0) && (client->txcount > client->MRC)) { - log_info("Max retransmission count exceeded."); + switch(check_timing6(client, DHCPV6_CONFIRM, "Confirm", + client->active_lease, &ds)) { + case CHK_TIM_MRC_EXCEEDED: + case CHK_TIM_MRD_EXCEEDED: start_bound(client); return; - } - - /* - * 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; - } - if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) { - log_info("Max retransmission duration exceeded."); - start_bound(client); + case CHK_TIM_ALLOC_FAILURE: return; + case CHK_TIM_SUCCESS: + break; } - memset(&ds, 0, sizeof(ds)); - if (!buffer_allocate(&ds.buffer, 4, MDL)) { - log_error("Unable to allocate memory for Confirm."); - return; - } - ds.data = ds.buffer->data; - ds.len = 4; - - ds.buffer->data[0] = DHCPV6_CONFIRM; - 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; - } - - if (client->elapsed == 0) - log_debug("XMT: Forming Confirm, 0 ms elapsed."); - else - log_debug("XMT: Forming Confirm, %u0 ms elapsed.", - (unsigned)client->elapsed); - - client->elapsed = htons(client->elapsed); - - make_client6_options(client, &client->sent_options, - client->active_lease, DHCPV6_CONFIRM); - /* Fetch any configured 'sent' options (includes DUID') in wire format. */ dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL, @@ -2182,17 +2117,14 @@ do_release6(void *input) if ((client->active_lease == NULL) || !active_prefix(client)) return; - if ((client->MRC != 0) && (client->txcount > client->MRC)) { - log_info("Max retransmission count exceeded."); + switch(check_timing6(client, DHCPV6_RELEASE, "Release", + client->active_lease, &ds)) { + case CHK_TIM_MRC_EXCEEDED: + case CHK_TIM_ALLOC_FAILURE: + case CHK_TIM_MRD_EXCEEDED: goto release_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; + case CHK_TIM_SUCCESS: + break; } /* @@ -2200,20 +2132,6 @@ do_release6(void *input) * available address with enough scope. */ - memset(&ds, 0, sizeof(ds)); - if (!buffer_allocate(&ds.buffer, 4, MDL)) { - log_error("Unable to allocate memory for Release."); - goto release_done; - } - - ds.data = ds.buffer->data; - ds.len = 4; - ds.buffer->data[0] = DHCPV6_RELEASE; - memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3); - - log_debug("XMT: Forming Release."); - make_client6_options(client, &client->sent_options, - client->active_lease, DHCPV6_RELEASE); dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL, client->sent_options, &global_scope, &dhcpv6_universe); @@ -3254,8 +3172,7 @@ do_select6(void *input) struct client_state *client; struct dhc6_lease *lease; struct data_string ds; - struct timeval elapsed, tv; - int abort = ISC_FALSE; + struct timeval tv; int send_ret; client = input; @@ -3268,32 +3185,9 @@ do_select6(void *input) return; } - if ((client->MRC != 0) && (client->txcount > client->MRC)) { - log_info("Max retransmission count exceeded."); - abort = ISC_TRUE; - } - - /* - * 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; - } - if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) { - log_info("Max retransmission duration exceeded."); - abort = ISC_TRUE; - } - - if (abort) { + switch(check_timing6(client, DHCPV6_REQUEST, "Request", lease, &ds)) { + case CHK_TIM_MRC_EXCEEDED: + case CHK_TIM_MRD_EXCEEDED: log_debug("PRC: Lease %s failed.", print_hex_1(lease->server_id.len, lease->server_id.data, 56)); @@ -3307,8 +3201,11 @@ do_select6(void *input) start_selecting6(client); else start_init6(client); - return; + case CHK_TIM_ALLOC_FAILURE: + return; + case CHK_TIM_SUCCESS: + break; } /* Now make a packet that looks suspiciously like the one we @@ -3321,37 +3218,6 @@ do_select6(void *input) * construct for the iaid, then we can delve into this matter * more properly. In the time being, this will work. */ - memset(&ds, 0, sizeof(ds)); - if (!buffer_allocate(&ds.buffer, 4, MDL)) { - log_error("Unable to allocate memory for REQUEST."); - return; - } - ds.data = ds.buffer->data; - ds.len = 4; - - ds.buffer->data[0] = DHCPV6_REQUEST; - 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; - } - - if (client->elapsed == 0) - log_debug("XMT: Forming Request, 0 ms elapsed."); - else - log_debug("XMT: Forming Request, %u0 ms elapsed.", - (unsigned)client->elapsed); - - client->elapsed = htons(client->elapsed); - - make_client6_options(client, &client->sent_options, lease, - DHCPV6_REQUEST); /* Fetch any configured 'sent' options (includes DUID) in wire format. */