Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dhcpv6_client_service.c Source File

dhcpv6_client_service.c

00001 /*
00002  * Copyright (c) 2018-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "nsconfig.h"
00019 #include <string.h>
00020 #include <ns_types.h>
00021 #include <ns_trace.h>
00022 #include "nsdynmemLIB.h"
00023 #include "ns_list.h"
00024 #include "common_functions.h"
00025 
00026 #ifdef HAVE_DHCPV6
00027 #include "dhcp_service_api.h"
00028 #include "dhcpv6_client_api.h"
00029 #include "libDHCPv6/libDHCPv6.h"
00030 #include "NWK_INTERFACE/Include/protocol.h"
00031 
00032 #define TRACE_GROUP "DHP"
00033 
00034 typedef struct {
00035     dhcp_client_global_adress_cb *global_address_cb;
00036     uint16_t service_instance;
00037     uint16_t relay_instance;
00038     uint16_t sol_timeout;
00039     uint16_t sol_max_rt;
00040     uint8_t sol_max_rc;
00041     uint8_t libDhcp_instance;
00042     dhcp_duid_options_params_t duid;
00043     int8_t interface;
00044     bool renew_uses_solicit: 1;
00045     bool one_instance_interface: 1;
00046     bool no_address_hint: 1;
00047     ns_list_link_t      link;                   /*!< List link entry */
00048 } dhcp_client_class_t;
00049 
00050 static NS_LARGE NS_LIST_DEFINE(dhcp_client_list, dhcp_client_class_t, link);
00051 
00052 static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr);
00053 void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason);
00054 
00055 
00056 
00057 static dhcp_client_class_t *dhcpv6_client_entry_allocate(int8_t interface, uint8_t duid_length)
00058 {
00059     dhcp_client_class_t *entry = ns_dyn_mem_alloc(sizeof(dhcp_client_class_t));
00060     uint8_t *duid  = ns_dyn_mem_alloc(duid_length);
00061     if (!entry || !duid) {
00062         ns_dyn_mem_free(entry);
00063         ns_dyn_mem_free(duid);
00064         return NULL;
00065 
00066     }
00067     memset(entry, 0, sizeof(dhcp_client_class_t));
00068     entry->interface = interface;
00069     entry->service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL);
00070     entry->libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id();
00071     entry->duid.duid = duid;
00072     entry->duid.duid_length = duid_length;
00073     entry->duid.type = DHCPV6_DUID_LINK_LAYER_TYPE;
00074     ns_list_add_to_end(&dhcp_client_list, entry);
00075     return entry;
00076 }
00077 
00078 //Discover DHCPv6 client
00079 static dhcp_client_class_t *dhcpv6_client_entry_discover(int8_t interface)
00080 {
00081     ns_list_foreach(dhcp_client_class_t, cur, &dhcp_client_list) {
00082         //Check All allocated address in this module
00083         if (cur->interface == interface) {
00084             return cur;
00085         }
00086     }
00087 
00088     return NULL;
00089 }
00090 
00091 
00092 void dhcp_client_init(int8_t interface, uint16_t link_type)
00093 {
00094     protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface);
00095     if (!interface_ptr) {
00096         return;
00097     }
00098 
00099 
00100     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
00101 
00102     if (dhcp_client) {
00103         dhcp_client->sol_timeout = 0;
00104         dhcp_client->sol_max_rt = 0;
00105         dhcp_client->sol_max_rc = 0;
00106         dhcp_client->renew_uses_solicit = false;
00107         dhcp_client->one_instance_interface = false;
00108         dhcp_client->no_address_hint = false;
00109         dhcp_client->service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL);
00110         dhcp_client->libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id();
00111         return;
00112     }
00113     //Allocate new
00114     //define DUID-LL length based on MAC64 or MAC48
00115 
00116     dhcp_client = dhcpv6_client_entry_allocate(interface, libdhcpv6_duid_linktype_size(link_type) + 2);
00117     if (!dhcp_client) {
00118         return;
00119     }
00120 
00121     uint8_t *ptr = dhcp_client->duid.duid;
00122     ptr = common_write_16_bit(link_type, ptr);
00123     memcpy(ptr, interface_ptr->mac, libdhcpv6_duid_linktype_size(link_type));
00124 
00125     //Define DUID
00126 
00127 
00128 }
00129 void dhcp_client_configure(int8_t interface, bool renew_uses_solicit, bool one_client_for_this_interface, bool no_address_hint)
00130 {
00131     // Set true if RENEW is not used and SOLICIT sent instead.
00132     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
00133     if (!dhcp_client) {
00134         return;
00135     }
00136     dhcp_client->renew_uses_solicit = renew_uses_solicit;
00137     dhcp_client->one_instance_interface = one_client_for_this_interface;
00138     dhcp_client->no_address_hint = no_address_hint;
00139 }
00140 
00141 void dhcp_client_solicit_timeout_set(int8_t interface, uint16_t timeout, uint16_t max_rt, uint8_t max_rc)
00142 {
00143     // Set the default retry values for SOLICIT and RENEW messages.
00144     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
00145     if (!dhcp_client) {
00146         return;
00147     }
00148     dhcp_client->sol_timeout = timeout;
00149     dhcp_client->sol_max_rt = max_rt;
00150     dhcp_client->sol_max_rc = max_rc;
00151 
00152     return;
00153 }
00154 
00155 void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16])
00156 {
00157     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
00158     if (!dhcp_client) {
00159         return;
00160     }
00161 
00162     dhcp_client->relay_instance = dhcp_service_init(interface, DHCP_INTANCE_RELAY_AGENT, NULL);
00163     dhcp_service_relay_instance_enable(dhcp_client->relay_instance, border_router_address);
00164 }
00165 
00166 void dhcp_client_delete(int8_t interface)
00167 {
00168     protocol_interface_info_entry_t *cur = NULL;
00169     dhcpv6_client_server_data_t *srv_data_ptr;
00170     uint8_t temporary_address[16];
00171     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
00172     if (!dhcp_client) {
00173         return;
00174     }
00175 
00176 
00177     dhcp_service_delete(dhcp_client->service_instance);
00178 
00179 
00180     cur = protocol_stack_interface_info_get_by_id(interface);
00181 
00182     if (!cur) {
00183         return;
00184     }
00185 
00186     do {
00187         srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
00188         if (srv_data_ptr != NULL) {
00189             tr_debug("Free DHCPv6 Client\n");
00190             memcpy(temporary_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, 16);
00191             dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
00192             libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
00193             addr_delete(cur, temporary_address);
00194 
00195         }
00196     } while (srv_data_ptr != NULL);
00197     dhcp_client->service_instance = 0;
00198     return;
00199 }
00200 
00201 
00202 void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr)
00203 {
00204     if (srv_data_ptr != NULL) {
00205         dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(srv_data_ptr->interfaceId);
00206         if (!dhcp_client) {
00207             return;
00208         }
00209 
00210         // error for Global address
00211         if (dhcp_client->global_address_cb != NULL) {
00212             dhcp_client->global_address_cb(dhcp_client->interface, srv_data_ptr->server_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, false);
00213         }
00214     }
00215 }
00216 
00217 
00218 /* solication responce received for either global address or routter id assignment */
00219 int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name,  uint8_t *msg_ptr, uint16_t msg_len)
00220 {
00221     dhcp_ia_non_temporal_params_t dhcp_ia_non_temporal_params;
00222     dhcp_duid_options_params_t clientId;
00223     dhcp_duid_options_params_t serverId;
00224     dhcpv6_client_server_data_t *srv_data_ptr = NULL;
00225     (void)instance_id;
00226 
00227     //Validate that started TR ID class is still at list
00228     srv_data_ptr = libdhcpv6_nonTemporal_validate_class_pointer(ptr);
00229 
00230 
00231     if (srv_data_ptr == NULL) {
00232         tr_error("server data not found");
00233         goto error_exit;
00234     }
00235 
00236     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(srv_data_ptr->interfaceId);
00237     if (!dhcp_client) {
00238         tr_error("No DHCPv6 client avilabale");
00239         goto error_exit;
00240     }
00241 
00242 
00243     //Clear Active Transaction state
00244     srv_data_ptr->transActionId = 0;
00245 
00246     // Validate message
00247     if (msg_name != DHCPV6_REPLY_TYPE) {
00248         tr_error("invalid response");
00249         goto error_exit;
00250     }
00251 
00252     if (libdhcpv6_reply_message_option_validate(&clientId, &serverId, &dhcp_ia_non_temporal_params, msg_ptr, msg_len) != 0) {
00253         tr_error("Reply Not include all Options");
00254         goto error_exit;
00255     }
00256 
00257     if (libdhcpv6_nonTemporal_entry_get_by_iaid(dhcp_ia_non_temporal_params.iaId) != srv_data_ptr) {
00258         /* Validate server data availability */
00259         tr_error("Valid instance not found");
00260         goto error_exit;
00261     }
00262 
00263     if (srv_data_ptr->IAID != dhcp_ia_non_temporal_params.iaId) {
00264         tr_error("Wrong IAID");
00265         goto error_exit;
00266     }
00267 
00268     if (libdhcpv6_compare_DUID(&srv_data_ptr->clientDUID, &clientId) != 0) {
00269         tr_error("Not Valid Client Id");
00270         goto error_exit;
00271     }
00272 
00273     //Allocate dynamically new Server DUID if needed
00274     if (!srv_data_ptr->serverDynamic_DUID || serverId.duid_length > srv_data_ptr->dyn_server_duid_length) {
00275         //Allocate dynamic new bigger
00276         srv_data_ptr->dyn_server_duid_length = 0;
00277         ns_dyn_mem_free(srv_data_ptr->serverDynamic_DUID);
00278         srv_data_ptr->serverDynamic_DUID = ns_dyn_mem_alloc(serverId.duid_length);
00279         if (!srv_data_ptr->serverDynamic_DUID) {
00280             tr_error("Dynamic DUID alloc fail");
00281             goto error_exit;
00282         }
00283         srv_data_ptr->dyn_server_duid_length = serverId.duid_length;
00284     }
00285 
00286     //Copy Server DUID
00287     srv_data_ptr->serverDUID.duid = srv_data_ptr->serverDynamic_DUID;
00288     srv_data_ptr->serverDUID.type = serverId.type;
00289     srv_data_ptr->serverDUID.duid_length = serverId.duid_length;
00290     memcpy(srv_data_ptr->serverDUID.duid, serverId.duid, serverId.duid_length);
00291 
00292     if (dhcp_client->one_instance_interface && memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, dhcp_ia_non_temporal_params.nonTemporalAddress, 16)) {
00293 
00294         protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(dhcp_client->interface);
00295         if (cur) {
00296             addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
00297         }
00298     }
00299 
00300     memcpy(srv_data_ptr->iaNontemporalAddress.addressPrefix, dhcp_ia_non_temporal_params.nonTemporalAddress, 16);
00301     srv_data_ptr->iaNontemporalAddress.preferredTime = dhcp_ia_non_temporal_params.preferredValidLifeTime;
00302     srv_data_ptr->iaNontemporalAddress.validLifetime = dhcp_ia_non_temporal_params.validLifeTime;
00303     srv_data_ptr->T0 = dhcp_ia_non_temporal_params.T0;
00304     srv_data_ptr->T1  = dhcp_ia_non_temporal_params.T1;
00305 
00306 
00307     bool status = dhcpv6_client_set_address(dhcp_client->interface, srv_data_ptr);
00308 
00309 
00310     if (dhcp_client->global_address_cb) {
00311         dhcp_client->global_address_cb(dhcp_client->interface, srv_data_ptr->server_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, status);
00312     }
00313     return RET_MSG_ACCEPTED;
00314 error_exit:
00315     dhcpv6_client_send_error_cb(srv_data_ptr);
00316     return RET_MSG_ACCEPTED;
00317 }
00318 
00319 int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], dhcp_client_global_adress_cb *error_cb)
00320 {
00321     dhcpv6_solication_base_packet_s solPacket = {0};
00322 
00323     uint8_t *payload_ptr;
00324     uint32_t payload_len;
00325     dhcpv6_client_server_data_t *srv_data_ptr;
00326     bool add_prefix;
00327     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
00328 
00329     if (dhcp_addr == NULL  || !dhcp_client) {
00330         tr_error("Invalid parameters");
00331         return -1;
00332     }
00333 
00334     if (!prefix || dhcp_client->one_instance_interface) {
00335         //NULL Definition will only check That Interface is not generated
00336         srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
00337         if (srv_data_ptr) {
00338             //Already Created to same interface
00339             if (dhcp_client->one_instance_interface && prefix) {
00340                 if (srv_data_ptr->iaNonTemporalStructValid) {
00341                     if (memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, prefix, 8) == 0) {
00342                         return 0;
00343                     }
00344 
00345                     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface);
00346                     if (!cur) {
00347                         return -1;
00348                     }
00349 
00350                     dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
00351                     addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
00352                     srv_data_ptr->iaNonTemporalStructValid = false;
00353                     memcpy(srv_data_ptr->iaNontemporalAddress.addressPrefix, prefix, 8);
00354                     goto dhcp_address_get;
00355 
00356                 } else if (dhcp_client_server_address_update(interface, prefix, dhcp_addr) == 0) {
00357                     //DHCP server address OK
00358                     return 0;
00359                 }
00360             }
00361             return -1;
00362 
00363         }
00364     } else if (dhcp_client_server_address_update(interface, prefix, dhcp_addr) == 0) {
00365         //No need for allocate new
00366         return 0;
00367     }
00368 
00369     tr_debug("GEN new Dhcpv6 client %u", dhcp_client->libDhcp_instance);
00370     srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client->libDhcp_instance, prefix, dhcp_addr);
00371 
00372     if (!srv_data_ptr) {
00373         tr_error("OOM srv_data_ptr");
00374         return -1;
00375     }
00376     //SET DUID
00377     srv_data_ptr->clientDUID = dhcp_client->duid;
00378 
00379 dhcp_address_get:
00380 
00381     if (!prefix || dhcp_client->no_address_hint) {
00382         add_prefix = false;
00383     } else {
00384         add_prefix = prefix != NULL;
00385     }
00386 
00387     payload_len = libdhcpv6_solication_message_length(srv_data_ptr->clientDUID.duid_length, add_prefix, 0);
00388 
00389 
00390     payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
00391     if (!payload_ptr) {
00392         libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
00393         tr_error("OOM payload_ptr");
00394         return -1;
00395     }
00396 
00397     dhcp_client->global_address_cb = error_cb; //TODO Only supporting one instance globaly if we need more for different instances needs code.
00398     srv_data_ptr->GlobalAddress = true;
00399     // Build solicit
00400     solPacket.clientDUID = srv_data_ptr->clientDUID;
00401     solPacket.iaID = srv_data_ptr->IAID;
00402     solPacket.messageType = DHCPV6_SOLICATION_TYPE;
00403     solPacket.transActionId = libdhcpv6_txid_get();
00404     /*Non Temporal Address */
00405 
00406     if (prefix && !dhcp_client->no_address_hint) {
00407         dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
00408         nonTemporalAddress.requestedAddress = prefix;
00409         libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &solPacket, &nonTemporalAddress, NULL);
00410     } else {
00411         libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &solPacket, NULL, NULL);
00412     }
00413 
00414     // send solicit
00415     srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client->service_instance, 0, srv_data_ptr, dhcp_addr, payload_ptr, payload_len, dhcp_solicit_resp_cb);
00416     if (srv_data_ptr->transActionId == 0) {
00417         ns_dyn_mem_free(payload_ptr);
00418         libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
00419         return -1;
00420     }
00421     srv_data_ptr->iaNonTemporalStructValid = false;
00422     if (dhcp_client->sol_timeout != 0) {
00423         // Default retry values are modified from specification update to message
00424         dhcp_service_set_retry_timers(srv_data_ptr->transActionId, dhcp_client->sol_timeout, dhcp_client->sol_max_rt, dhcp_client->sol_max_rc);
00425     }
00426 
00427     return 0;
00428 }
00429 
00430 int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t server_address[static 16])
00431 {
00432     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
00433     if (!dhcp_client) {
00434         tr_debug("Interface not match");
00435         return -1;
00436     }
00437 
00438     dhcpv6_client_server_data_t *srv_data_ptr = NULL;
00439 
00440     if (prefix) {
00441         srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
00442     } else if (dhcp_client->one_instance_interface) {
00443         srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
00444     }
00445     if (!srv_data_ptr) {
00446         return -1;
00447     }
00448 
00449     if (memcmp(srv_data_ptr->server_address, server_address, 16) == 0) {
00450         return 0;
00451     }
00452 
00453     memcpy(srv_data_ptr->server_address, server_address, 16);
00454     if (srv_data_ptr->transActionId) {
00455         dhcp_service_update_server_address(srv_data_ptr->transActionId, server_address);
00456     }
00457     return 0;
00458 }
00459 
00460 
00461 
00462 void dhcp_client_global_address_renew(int8_t interface)
00463 {
00464     (void)interface;
00465     return;
00466 }
00467 
00468 void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uint8_t prefix[static 16])
00469 {
00470     protocol_interface_info_entry_t *cur;
00471     dhcpv6_client_server_data_t *srv_data_ptr;
00472     dhcp_client_class_t *dhcp_client;
00473     (void) dhcp_addr;
00474 
00475     srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
00476     cur = protocol_stack_interface_info_get_by_id(interface);
00477     dhcp_client = dhcpv6_client_entry_discover(interface);
00478 
00479     if (cur == NULL || srv_data_ptr == NULL || !dhcp_client) {
00480         return;
00481     }
00482 
00483     dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
00484     if (dhcp_client->one_instance_interface) {
00485         addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
00486     } else {
00487         addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
00488     }
00489 
00490     libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
00491 }
00492 
00493 void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason)
00494 {
00495 
00496     uint8_t *payload_ptr;
00497     uint32_t payload_len;
00498     dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface->id);
00499     if (!dhcp_client) {
00500         return;
00501     }
00502 
00503     dhcpv6_client_server_data_t *srv_data_ptr;
00504     if (addr) {
00505         srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface->id, addr->address);
00506     } else {
00507         srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
00508     }
00509 
00510     if (srv_data_ptr == NULL) {
00511         return;
00512     }
00513     if (reason == ADDR_CALLBACK_INVALIDATED) {
00514         dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
00515         libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
00516         tr_warn("Dhcp address lost");
00517         return;
00518     }
00519 
00520     if (reason != ADDR_CALLBACK_TIMER) {
00521         return;
00522     }
00523 
00524     if (srv_data_ptr->transActionId) {
00525         //Do not trig new Renew process
00526         tr_warn("Do not trig new pending renew request");
00527         return;
00528     }
00529 
00530     payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientDUID.duid_length, srv_data_ptr->serverDUID.duid_length, 0, !dhcp_client->no_address_hint);
00531     payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
00532     if (payload_ptr == NULL) {
00533         if (addr) {
00534             addr->state_timer = 200; //Retry after 20 seconds
00535         }
00536         tr_error("Out of memory");
00537         return ;
00538     }
00539     dhcpv6_solication_base_packet_s packetReq = {
00540         .messageType = DHCPV6_RENEW_TYPE,
00541         .clientDUID = srv_data_ptr->clientDUID,
00542         .requestedOptionCnt = 0,
00543         .iaID = srv_data_ptr->IAID,
00544         .timerT0 = srv_data_ptr->T0,
00545         .timerT1 = srv_data_ptr->T1,
00546         .requestedOptionList = NULL,
00547     };
00548 
00549     if (dhcp_client->renew_uses_solicit) {
00550         packetReq.messageType = DHCPV6_SOLICATION_TYPE;
00551     }
00552 
00553 
00554 
00555     if (dhcp_client->no_address_hint && dhcp_client->renew_uses_solicit) {
00556         packetReq.timerT0 = 0;
00557         packetReq.timerT1 = 0;
00558         libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, NULL, &srv_data_ptr->serverDUID);
00559     } else {
00560         // Set Address information
00561         dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
00562         nonTemporalAddress.requestedAddress = srv_data_ptr->iaNontemporalAddress.addressPrefix;
00563         nonTemporalAddress.preferredLifeTime = srv_data_ptr->iaNontemporalAddress.preferredTime;
00564         nonTemporalAddress.validLifeTime = srv_data_ptr->iaNontemporalAddress.validLifetime;
00565         libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, &nonTemporalAddress, &srv_data_ptr->serverDUID);
00566     }
00567     // send solicit
00568     uint8_t *server_address = dhcp_service_relay_global_addres_get(dhcp_client->relay_instance);
00569     if (!server_address) {
00570         server_address = srv_data_ptr->server_address;
00571     }
00572 
00573     srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client->service_instance, 0, srv_data_ptr, server_address, payload_ptr, payload_len, dhcp_solicit_resp_cb);
00574     if (srv_data_ptr->transActionId == 0) {
00575         ns_dyn_mem_free(payload_ptr);
00576         if (addr) {
00577             addr->state_timer = 200; //Retry after 20 seconds
00578         }
00579         tr_error("DHCP renew send failed");
00580     }
00581     if (packetReq.messageType == DHCPV6_SOLICATION_TYPE && dhcp_client->sol_timeout != 0) {
00582         // Default retry values are modified from specification update to message
00583         dhcp_service_set_retry_timers(srv_data_ptr->transActionId, dhcp_client->sol_timeout, dhcp_client->sol_max_rt, dhcp_client->sol_max_rc);
00584     }
00585     tr_info("DHCP renew send OK");
00586 }
00587 
00588 static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr)
00589 {
00590     protocol_interface_info_entry_t *cur = NULL;
00591     if_address_entry_t *address_entry = NULL;
00592     uint32_t renewTimer;
00593     cur = protocol_stack_interface_info_get_by_id(interface_id);
00594     if (!cur) {
00595         return false;
00596     }
00597     renewTimer = libdhcpv6_renew_time_define(srv_data_ptr);
00598 
00599     srv_data_ptr->iaNonTemporalStructValid = true;
00600     address_entry = addr_get_entry(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
00601     if (address_entry == NULL) {
00602         // create new
00603         address_entry = addr_add(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix, 64, ADDR_SOURCE_DHCP, srv_data_ptr->iaNontemporalAddress.validLifetime, srv_data_ptr->iaNontemporalAddress.preferredTime, false);
00604     } else {
00605         addr_set_valid_lifetime(cur, address_entry, srv_data_ptr->iaNontemporalAddress.validLifetime);
00606         addr_set_preferred_lifetime(cur, address_entry, srv_data_ptr->iaNontemporalAddress.preferredTime);
00607     }
00608 
00609     if (address_entry == NULL) {
00610         tr_error("Address add failed");
00611         srv_data_ptr->iaNonTemporalStructValid = false;
00612         return false;
00613     }
00614 
00615     if (renewTimer) {
00616         // translate seconds to 100ms ticks
00617         if (renewTimer  <  0xffffffff / 10) {
00618             renewTimer *= 10;
00619         } else {
00620             renewTimer = 0xfffffffe;
00621         }
00622     }
00623     address_entry->state_timer = renewTimer;
00624     address_entry->cb = dhcpv6_renew;
00625     return true;
00626 }
00627 
00628 #endif