diff options
author | Francis Dupont <fdupont@isc.org> | 2008-10-22 11:41:58 +0000 |
---|---|---|
committer | Francis Dupont <fdupont@isc.org> | 2008-10-22 11:41:58 +0000 |
commit | 783259b1cced2dc577cc2159990389235b36f858 (patch) | |
tree | bedd950f7aa63eb4030cd51f5e0a115b455f2067 /server | |
parent | 399d3dbe291579f9cda4407bebaf0188724e48a2 (diff) | |
download | isc-dhcp-783259b1cced2dc577cc2159990389235b36f858.tar.gz |
Improve IA_TA server support (17586)
Diffstat (limited to 'server')
-rw-r--r-- | server/confpars.c | 27 | ||||
-rw-r--r-- | server/dhcpd.conf.5 | 8 | ||||
-rw-r--r-- | server/dhcpv6.c | 210 | ||||
-rw-r--r-- | server/mdb6.c | 46 |
4 files changed, 216 insertions, 75 deletions
diff --git a/server/confpars.c b/server/confpars.c index 0a25cc44..f8e82266 100644 --- a/server/confpars.c +++ b/server/confpars.c @@ -3753,7 +3753,7 @@ add_ipv6_pool_to_subnet(struct subnet *subnet, u_int16_t type, /* address-range6-declaration :== ip-address6 ip-address6 SEMI | ip-address6 SLASH number SEMI - | ip-address6 TEMPORARY SEMI */ + | ip-address6 [SLASH number] TEMPORARY SEMI */ void parse_address_range6(struct parse *cfile, struct group *group) { @@ -3763,6 +3763,7 @@ parse_address_range6(struct parse *cfile, struct group *group) { const char *val; struct iaddrcidrnetlist *nets; struct iaddrcidrnetlist *p; + u_int16_t type = D6O_IA_NA; if (local_family != AF_INET6) { parse_warn(cfile, "range6 statement is only supported " @@ -3809,13 +3810,27 @@ parse_address_range6(struct parse *cfile, struct group *group) { return; } - add_ipv6_pool_to_subnet(group->subnet, D6O_IA_NA, &lo, bits, - 128); + /* + * can be temporary (RFC 4941 like) + */ + token = peek_token(&val, NULL, cfile); + if (token == TEMPORARY) { + if (bits < 64) + parse_warn(cfile, "temporary mask too short"); + if (bits == 128) + parse_warn(cfile, "temporary singleton?"); + token = next_token(NULL, NULL, cfile); + type = D6O_IA_TA; + } + + add_ipv6_pool_to_subnet(group->subnet, type, &lo, + bits, 128); } else if (token == TEMPORARY) { /* * temporary (RFC 4941) */ + type = D6O_IA_TA; next_token(NULL, NULL, cfile); bits = 64; if (!is_cidr_mask_valid(&lo, bits)) { @@ -3824,8 +3839,8 @@ parse_address_range6(struct parse *cfile, struct group *group) { return; } - add_ipv6_pool_to_subnet(group->subnet, D6O_IA_TA, &lo, bits, - 128); + add_ipv6_pool_to_subnet(group->subnet, type, &lo, + bits, 128); } else { /* * No '/', so we are looking for the end address of @@ -3844,7 +3859,7 @@ parse_address_range6(struct parse *cfile, struct group *group) { } for (p=nets; p != NULL; p=p->next) { - add_ipv6_pool_to_subnet(group->subnet, D6O_IA_NA, + add_ipv6_pool_to_subnet(group->subnet, type, &p->cidrnet.lo_addr, p->cidrnet.bits, 128); } diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5 index 47ef2571..238b8d74 100644 --- a/server/dhcpd.conf.5 +++ b/server/dhcpd.conf.5 @@ -28,7 +28,7 @@ .\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see .\" ``http://www.nominum.com''. .\" -.\" $Id: dhcpd.conf.5,v 1.97 2008/08/19 17:55:57 dhankins Exp $ +.\" $Id: dhcpd.conf.5,v 1.98 2008/10/22 11:41:58 fdupont Exp $ .\" .TH dhcpd.conf 5 .SH NAME @@ -1521,6 +1521,7 @@ single address, \fIhigh-address\fR can be omitted. .nf .B range6\fR \fIlow-address\fR \fIhigh-address\fR\fB;\fR .B range6\fR \fIsubnet6-number\fR\fB;\fR +.B range6\fR \fIsubnet6-number\fR \fBtemporary\fR\fB;\fR .B range6\fR \fIaddress\fR \fBtemporary\fR\fB;\fR .fi .PP @@ -1531,11 +1532,10 @@ 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 -The \fItemporary\fR variant makes the 64 bit prefix \fIaddress\fR available +The \fItemporay\fR variant makes the prefix (by default on 64 bits) available for temporary (RFC 4941) addresses. A new address per prefix in the shared network is computed at each request with an IA_TA option. Release and Confirm -ignores temporary addresses, Renew and Rebind are not defined and raise an -error. +ignores temporary addresses. .PP Any IPv6 addresses given to hosts with \fIfixed-address6\fR are excluded from the \fIrange6\fR, as are IPv6 addresses on the server itself. diff --git a/server/dhcpv6.c b/server/dhcpv6.c index 3aa6610e..054e5c1d 100644 --- a/server/dhcpv6.c +++ b/server/dhcpv6.c @@ -109,6 +109,8 @@ static isc_result_t reply_process_addr(struct reply_state *reply, struct option_cache *addr); static isc_boolean_t address_is_owned(struct reply_state *reply, struct iaddr *addr); +static isc_boolean_t temporary_is_available(struct reply_state *reply, + struct iaddr *addr); static isc_result_t find_client_temporaries(struct reply_state *reply); static isc_result_t reply_process_try_addr(struct reply_state *reply, struct iaddr *addr); @@ -178,7 +180,7 @@ static struct data_string server_duid; /* * Check if the server_duid has been set. */ -isc_boolean_t +isc_boolean_t server_duid_isset(void) { return (server_duid.data != NULL); } @@ -233,8 +235,8 @@ set_server_duid_from_option(void) { ret_val = ISC_R_NOTFOUND; } else { memset(&option_duid, 0, sizeof(option_duid)); - if (!evaluate_option_cache(&option_duid, NULL, NULL, NULL, - opt_state, NULL, &global_scope, + if (!evaluate_option_cache(&option_duid, NULL, NULL, NULL, + opt_state, NULL, &global_scope, oc, MDL)) { ret_val = ISC_R_UNEXPECTED; } else { @@ -308,32 +310,32 @@ generate_new_server_duid(void) { if (server_duid_type == DUID_LLT) { time_val = duid_time(time(NULL)); generated_duid.len = 8 + p->hw_address.hlen - 1; - if (!buffer_allocate(&generated_duid.buffer, + if (!buffer_allocate(&generated_duid.buffer, generated_duid.len, MDL)) { log_fatal("No memory for server DUID."); } generated_duid.data = generated_duid.buffer->data; putUShort(generated_duid.buffer->data, DUID_LLT); - putUShort(generated_duid.buffer->data + 2, + putUShort(generated_duid.buffer->data + 2, p->hw_address.hbuf[0]); putULong(generated_duid.buffer->data + 4, time_val); - memcpy(generated_duid.buffer->data + 8, + memcpy(generated_duid.buffer->data + 8, p->hw_address.hbuf+1, p->hw_address.hlen-1); } else if (server_duid_type == DUID_LL) { generated_duid.len = 4 + p->hw_address.hlen - 1; - if (!buffer_allocate(&generated_duid.buffer, + if (!buffer_allocate(&generated_duid.buffer, generated_duid.len, MDL)) { log_fatal("No memory for server DUID."); } generated_duid.data = generated_duid.buffer->data; putUShort(generated_duid.buffer->data, DUID_LL); - putUShort(generated_duid.buffer->data + 2, + putUShort(generated_duid.buffer->data + 2, p->hw_address.hbuf[0]); - memcpy(generated_duid.buffer->data +4, + memcpy(generated_duid.buffer->data + 4, p->hw_address.hbuf+1, p->hw_address.hlen-1); } else { log_fatal("Unsupported server DUID type %d.", server_duid_type); - } + } set_server_duid(&generated_duid); data_string_forget(&generated_duid, MDL); @@ -360,7 +362,7 @@ get_client_id(struct packet *packet, struct data_string *client_id) { return ISC_R_NOTFOUND; } - if (!evaluate_option_cache(client_id, packet, NULL, NULL, + if (!evaluate_option_cache(client_id, packet, NULL, NULL, packet->options, NULL, &global_scope, oc, MDL)) { return ISC_R_FAILURE; @@ -391,7 +393,7 @@ valid_client_msg(struct packet *packet, struct data_string *client_id) { break; case ISC_R_NOTFOUND: log_debug("Discarding %s from %s; " - "client identifier missing", + "client identifier missing", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr)); goto exit; @@ -408,7 +410,7 @@ valid_client_msg(struct packet *packet, struct data_string *client_id) { */ if (packet->unicast) { log_debug("Discarding %s from %s; packet sent unicast " - "(CLIENTID %s)", + "(CLIENTID %s)", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr), print_hex_1(client_id->len, client_id->data, 60)); @@ -419,23 +421,23 @@ valid_client_msg(struct packet *packet, struct data_string *client_id) { oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID); if (oc != NULL) { if (evaluate_option_cache(&data, packet, NULL, NULL, - packet->options, NULL, + packet->options, NULL, &global_scope, oc, MDL)) { - log_debug("Discarding %s from %s; " + log_debug("Discarding %s from %s; " "server identifier found " - "(CLIENTID %s, SERVERID %s)", + "(CLIENTID %s, SERVERID %s)", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr), - print_hex_1(client_id->len, + print_hex_1(client_id->len, client_id->data, 60), print_hex_2(data.len, data.data, 60)); } else { - log_debug("Discarding %s from %s; " + log_debug("Discarding %s from %s; " "server identifier found " - "(CLIENTID %s)", + "(CLIENTID %s)", dhcpv6_type_names[packet->dhcpv6_msg_type], - print_hex_1(client_id->len, + print_hex_1(client_id->len, client_id->data, 60), piaddr(packet->client_addr)); } @@ -488,7 +490,7 @@ valid_client_resp(struct packet *packet, break; case ISC_R_NOTFOUND: log_debug("Discarding %s from %s; " - "client identifier missing", + "client identifier missing", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr)); goto exit; @@ -503,13 +505,13 @@ valid_client_resp(struct packet *packet, oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID); if (oc == NULL) { log_debug("Discarding %s from %s: " - "server identifier missing (CLIENTID %s)", + "server identifier missing (CLIENTID %s)", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr), print_hex_1(client_id->len, client_id->data, 60)); goto exit; } - if (!evaluate_option_cache(server_id, packet, NULL, NULL, + if (!evaluate_option_cache(server_id, packet, NULL, NULL, packet->options, NULL, &global_scope, oc, MDL)) { log_error("Error processing %s from %s; " @@ -519,11 +521,11 @@ valid_client_resp(struct packet *packet, print_hex_1(client_id->len, client_id->data, 60)); goto exit; } - if ((server_duid.len != server_id->len) || + if ((server_duid.len != server_id->len) || (memcmp(server_duid.data, server_id->data, server_duid.len) != 0)) { - log_debug("Discarding %s from %s; " + log_debug("Discarding %s from %s; " "not our server identifier " - "(CLIENTID %s, SERVERID %s, server DUID %s)", + "(CLIENTID %s, SERVERID %s, server DUID %s)", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr), print_hex_1(client_id->len, client_id->data, 60), @@ -598,7 +600,7 @@ valid_client_info_req(struct packet *packet, struct data_string *server_id) { oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA); if (oc != NULL) { log_debug("Discarding %s from %s; " - "IA_NA option present%s", + "IA_NA option present%s", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr), client_id_str); goto exit; @@ -606,7 +608,7 @@ valid_client_info_req(struct packet *packet, struct data_string *server_id) { oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA); if (oc != NULL) { log_debug("Discarding %s from %s; " - "IA_TA option present%s", + "IA_TA option present%s", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr), client_id_str); goto exit; @@ -614,7 +616,7 @@ valid_client_info_req(struct packet *packet, struct data_string *server_id) { oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD); if (oc != NULL) { log_debug("Discarding %s from %s; " - "IA_PD option present%s", + "IA_PD option present%s", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr), client_id_str); goto exit; @@ -622,7 +624,7 @@ valid_client_info_req(struct packet *packet, struct data_string *server_id) { oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID); if (oc != NULL) { - if (!evaluate_option_cache(server_id, packet, NULL, NULL, + if (!evaluate_option_cache(server_id, packet, NULL, NULL, packet->options, NULL, &global_scope, oc, MDL)) { log_error("Error processing %s from %s; " @@ -631,17 +633,17 @@ valid_client_info_req(struct packet *packet, struct data_string *server_id) { piaddr(packet->client_addr), client_id_str); goto exit; } - if ((server_duid.len != server_id->len) || - (memcmp(server_duid.data, server_id->data, + if ((server_duid.len != server_id->len) || + (memcmp(server_duid.data, server_id->data, server_duid.len) != 0)) { - log_debug("Discarding %s from %s; " + log_debug("Discarding %s from %s; " "not our server identifier " - "(SERVERID %s, server DUID %s)%s", + "(SERVERID %s, server DUID %s)%s", dhcpv6_type_names[packet->dhcpv6_msg_type], piaddr(packet->client_addr), - print_hex_1(server_id->len, + print_hex_1(server_id->len, server_id->data, 60), - print_hex_2(server_duid.len, + print_hex_2(server_duid.len, server_duid.data, 60), client_id_str); goto exit; @@ -716,7 +718,7 @@ static const int required_opts_STATUS_CODE[] = { * where in the IA_* the DHCPv6 options commence. */ static int -get_encapsulated_IA_state(struct option_state **enc_opt_state, +get_encapsulated_IA_state(struct option_state **enc_opt_state, struct data_string *enc_opt_data, struct packet *packet, struct option_cache *oc, @@ -749,7 +751,7 @@ get_encapsulated_IA_state(struct option_state **enc_opt_state, data_string_forget(enc_opt_data, MDL); return 0; } - if (!parse_option_buffer(*enc_opt_state, + if (!parse_option_buffer(*enc_opt_state, enc_opt_data->data + offset, enc_opt_data->len - offset, &dhcpv6_universe)) { @@ -2214,6 +2216,7 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { struct data_string ia_data, data; struct data_string iaaddr; u_int32_t pref_life, valid_life; + struct iaddr tmp_addr; /* Initialize values that will get cleaned up on return. */ packet_ia = NULL; @@ -2240,7 +2243,7 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { iaid = getULong(ia_data.data); /* Create an IA_TA structure. */ - if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, + if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, reply->client_id.len, MDL) != ISC_R_SUCCESS) { log_error("reply_process_ia_ta: no memory for ia."); status = ISC_R_NOMEMORY; @@ -2289,11 +2292,13 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { /* * Deal with an IAADDR for lifetimes. + * For all or none, process IAADDRs as hints. */ reply->valid = reply->prefer = 0xffffffff; reply->client_valid = reply->client_prefer = 0; oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR); - if (oc != NULL) { + for (; oc != NULL; oc = oc->next) { + memset(&iaaddr, 0, sizeof(iaaddr)); if (!evaluate_option_cache(&iaaddr, reply->packet, NULL, NULL, reply->packet->options, NULL, @@ -2315,29 +2320,47 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { if ((reply->client_prefer == 0) || (reply->client_prefer > pref_life)) reply->client_prefer = pref_life; - } - reply->ia_count++; - /* - * Cancel if not Solicit or Request. - */ - if ((reply->packet->dhcpv6_msg_type != DHCPV6_SOLICIT) && - (reply->packet->dhcpv6_msg_type != DHCPV6_REQUEST)) { - if (!set_status_code(STATUS_UnspecFail, - "Unsupported message for temporary.", - reply->reply_ia)) { - log_error("reply_process_ia_ta: Unable to set " - "UnspecFail status code."); - status = ISC_R_FAILURE; + /* Nothing more if something has failed. */ + if (status == ISC_R_CANCELED) + continue; + + tmp_addr.len = 16; + memcpy(tmp_addr.iabuf, iaaddr.data, 16); + if (!temporary_is_available(reply, &tmp_addr)) + goto bad_temp; + status = reply_process_is_addressed(reply, + &reply->lease->scope, + reply->shared->group); + if (status != ISC_R_SUCCESS) + goto bad_temp; + status = reply_process_send_addr(reply, &tmp_addr); + if (status != ISC_R_SUCCESS) + goto bad_temp; + if (reply->lease != NULL) + iasubopt_dereference(&reply->lease, MDL); + continue; + + bad_temp: + /* Rewind the IA_TA to empty. */ + option_state_dereference(&reply->reply_ia, MDL); + if (!option_state_allocate(&reply->reply_ia, MDL)) { + status = ISC_R_NOMEMORY; goto cleanup; } status = ISC_R_CANCELED; - goto store; + reply->client_resources = 0; + reply->resources_included = ISC_FALSE; + if (reply->lease != NULL) + iasubopt_dereference(&reply->lease, MDL); } + reply->ia_count++; /* * Give the client temporary addresses. */ + if (reply->client_resources != 0) + goto store; status = find_client_temporaries(reply); if (status == ISC_R_NORESOURCES) { switch (reply->packet->dhcpv6_msg_type) { @@ -2380,8 +2403,16 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { break; default: - /* Should not happen! */ - goto cleanup; + /* + * We don't want to include the IA if we + * provide zero addresses including zeroed + * lifetimes. + */ + if (reply->resources_included) + status = ISC_R_SUCCESS; + else + goto cleanup; + break; } } else if (status != ISC_R_SUCCESS) goto cleanup; @@ -2480,13 +2511,78 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { /* * ISC_R_CANCELED is a status code used by the addr processing to - * indicate we're replying with a status code. This is still a + * indicate we're replying with other addresses. This is still a * success at higher layers. */ return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status); } /* + * Verify the temporary address is available. + */ +static isc_boolean_t +temporary_is_available(struct reply_state *reply, struct iaddr *addr) { + struct in6_addr tmp_addr; + struct subnet *subnet; + struct ipv6_pool *pool; + int i; + + memcpy(&tmp_addr, addr->iabuf, sizeof(tmp_addr)); + /* + * Clients may choose to send :: as an address, with the idea to give + * hints about preferred-lifetime or valid-lifetime. + * So this is not a request for this address. + */ + if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) + return ISC_FALSE; + + /* + * Verify that this address is on the client's network. + */ + for (subnet = reply->shared->subnets ; subnet != NULL ; + subnet = subnet->next_sibling) { + if (addr_eq(subnet_number(*addr, subnet->netmask), + subnet->net)) + break; + } + + /* Address not found on shared network. */ + if (subnet == NULL) + return ISC_FALSE; + + /* + * Check if this address is owned (must be before next step). + */ + if (address_is_owned(reply, addr)) + return ISC_TRUE; + + /* + * Verify that this address is in a temporary pool and try to get it. + */ + if (reply->shared->ipv6_pools == NULL) + return ISC_FALSE; + for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) { + if (pool->pool_type != D6O_IA_TA) + continue; + if (ipv6_in_pool(&tmp_addr, pool)) + break; + } + if (pool == NULL) + return ISC_FALSE; + if (lease6_exists(pool, &tmp_addr)) + return ISC_FALSE; + if (iasubopt_allocate(&reply->lease, MDL) != ISC_R_SUCCESS) + return ISC_FALSE; + reply->lease->addr = tmp_addr; + reply->lease->plen = 0; + /* Default is soft binding for 2 minutes. */ + if (add_lease6(pool, reply->lease, cur_time + 120) != ISC_R_SUCCESS) + return ISC_FALSE; + + return ISC_TRUE; +} + +/* * Get a temporary address per prefix. */ static isc_result_t diff --git a/server/mdb6.c b/server/mdb6.c index 3c689913..a5ae4eb7 100644 --- a/server/mdb6.c +++ b/server/mdb6.c @@ -619,12 +619,12 @@ build_address6(struct in6_addr *addr, MD5_Final((unsigned char *)addr, &ctx); /* - * Copy the network bits over. + * Copy the [0..128] network bits over. */ str = (char *)addr; net_str = (const char *)net_start_addr; net_bytes = net_bits / 8; - for (i=0; i<net_bytes; i++) { + for (i = 0; i < net_bytes; i++) { str[i] = net_str[i]; } switch (net_bits % 8) { @@ -643,10 +643,11 @@ build_address6(struct in6_addr *addr, /* * Create a temporary address by a variant of RFC 4941 algo. + * Note: this should not be used for prefixes shorter than 64 bits. */ static void build_temporary6(struct in6_addr *addr, - const struct in6_addr *net_start_addr, + const struct in6_addr *net_start_addr, int net_bits, const struct data_string *input) { static u_int8_t history[8]; static u_int32_t counter = 0; @@ -674,9 +675,37 @@ build_temporary6(struct in6_addr *addr, /* * Build the address. */ - memcpy(&addr->s6_addr[0], &net_start_addr->s6_addr[0], 8); - memcpy(&addr->s6_addr[8], md, 8); - addr->s6_addr[8] &= ~0x02; + if (net_bits == 64) { + memcpy(&addr->s6_addr[0], &net_start_addr->s6_addr[0], 8); + memcpy(&addr->s6_addr[8], md, 8); + addr->s6_addr[8] &= ~0x02; + } else { + int net_bytes; + int i; + char *str; + const char *net_str; + + /* + * Copy the [0..128] network bits over. + */ + str = (char *)addr; + net_str = (const char *)net_start_addr; + net_bytes = net_bits / 8; + for (i = 0; i < net_bytes; i++) { + str[i] = net_str[i]; + } + memcpy(str + net_bytes, md, 16 - net_bytes); + switch (net_bits % 8) { + case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break; + case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break; + case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break; + case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break; + case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break; + case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break; + case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break; + } + } + /* * Save history for the next call. @@ -762,7 +791,8 @@ create_lease6(struct ipv6_pool *pool, struct iasubopt **addr, break; case D6O_IA_TA: /* temporary address */ - build_temporary6(&tmp, &pool->start_addr, &ds); + build_temporary6(&tmp, &pool->start_addr, + pool->bits, &ds); break; case D6O_IA_PD: /* prefix */ @@ -1133,7 +1163,7 @@ build_prefix6(struct in6_addr *pref, str = (char *)pref; net_str = (const char *)net_start_pref; net_bytes = pool_bits / 8; - for (i=0; i<net_bytes; i++) { + for (i = 0; i < net_bytes; i++) { str[i] = net_str[i]; } i = net_bytes; |