Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dhcp_service_api.c Source File

dhcp_service_api.c

00001 /*
00002  * Copyright (c) 2013-2017, 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 
00020 #include <string.h>
00021 #include <ns_types.h>
00022 #include <ns_trace.h>
00023 #include "eventOS_event.h"
00024 #include "eventOS_scheduler.h"
00025 #include "eventOS_event_timer.h"
00026 #include "nsdynmemLIB.h"
00027 #include "ns_list.h"
00028 #include "randLIB.h"
00029 #include "socket_api.h"
00030 #include "net_interface.h"
00031 #include "common_functions.h"
00032 #include "libDHCPv6/libDHCPv6.h"
00033 #include "NWK_INTERFACE/Include/protocol.h" // just for protocol_core_monotonic_time
00034 
00035 #include "dhcp_service_api.h"
00036 #ifdef HAVE_DHCPV6
00037 #define TRACE_GROUP    "dhcp"
00038 
00039 #define MAX_SERVERS 20
00040 
00041 /* Fixed-point randomisation limits for randlib_randomise_base() - RFC 3315
00042  * says RAND is uniformly distributed between -0.1 and +0.1
00043  */
00044 #define RAND1_LOW   0x7333 // 1 - 0.1; minimum for "1+RAND"
00045 #define RAND1_HIGH  0x8CCD // 1 + 0.1; maximum for "1+RAND"
00046 
00047 typedef struct {
00048     dhcp_service_receive_req_cb *recv_req_cb;
00049     uint16_t instance_id;
00050     int8_t interface_id;
00051     dhcp_instance_type_e instance_type;
00052     ns_list_link_t link;
00053 } server_instance_t;
00054 typedef NS_LIST_HEAD (server_instance_t, link) server_instance_list_t;
00055 
00056 typedef struct {
00057     ns_address_t addr;
00058     dhcp_service_receive_resp_cb *recv_resp_cb;
00059     uint16_t instance_id;
00060     int8_t interface_id;
00061     int8_t socket;
00062     uint8_t options;
00063     void  *client_obj_ptr;
00064     uint32_t msg_tr_id;
00065     uint32_t message_tr_id;
00066     uint32_t first_transmit_time;
00067     uint16_t timeout;
00068     uint16_t timeout_init;
00069     uint16_t timeout_max;
00070     uint8_t retrans_max;
00071     uint8_t retrans;
00072     uint8_t *msg_ptr;
00073     uint16_t msg_len;
00074     ns_list_link_t link;
00075 } msg_tr_t;
00076 typedef NS_LIST_HEAD (msg_tr_t, link) tr_list_t;
00077 
00078 typedef struct {
00079     ns_address_t src_address;
00080     server_instance_list_t srv_list;
00081     tr_list_t tr_list;
00082     int8_t dhcp_server_socket;
00083     int8_t dhcp_client_socket;
00084     int8_t dhcpv6_socket_service_tasklet;
00085 } dhcp_service_class_t;
00086 
00087 #define DHCPV6_SOCKET_SERVICE_TASKLET_INIT      1
00088 #define DHCPV6_SOCKET_SERVICE_TIMER             2
00089 
00090 #define DHCPV6_SOCKET_SERVICE_TIMER_ID          1
00091 
00092 #define DHCPV6_SOCKET_TIMER_UPDATE_PERIOD_IN_MS 100
00093 
00094 dhcp_service_class_t *dhcp_service = NULL;
00095 static bool dhcpv6_socket_timeout_timer_active = false;
00096 
00097 void dhcp_service_send_message(msg_tr_t *msg_tr_ptr);
00098 
00099 void DHCPv6_socket_service_tasklet(arm_event_s *event)
00100 {
00101     if (event->event_type == DHCPV6_SOCKET_SERVICE_TASKLET_INIT) {
00102         //We should define peridiocally timer service!!
00103         eventOS_event_timer_request(DHCPV6_SOCKET_SERVICE_TIMER_ID, DHCPV6_SOCKET_SERVICE_TIMER, dhcp_service->dhcpv6_socket_service_tasklet, DHCPV6_SOCKET_TIMER_UPDATE_PERIOD_IN_MS);
00104         dhcpv6_socket_timeout_timer_active = true;
00105     } else if (event->event_type == DHCPV6_SOCKET_SERVICE_TIMER) {
00106 
00107         if (dhcp_service_timer_tick(1)) {
00108             dhcpv6_socket_timeout_timer_active = true;
00109             eventOS_event_timer_request(DHCPV6_SOCKET_SERVICE_TIMER_ID, DHCPV6_SOCKET_SERVICE_TIMER, dhcp_service->dhcpv6_socket_service_tasklet, DHCPV6_SOCKET_TIMER_UPDATE_PERIOD_IN_MS);
00110         } else {
00111             dhcpv6_socket_timeout_timer_active = false;
00112         }
00113     }
00114 }
00115 
00116 bool dhcp_service_allocate(void)
00117 {
00118     bool retVal = false;
00119     if (dhcp_service == NULL) {
00120         dhcp_service = ns_dyn_mem_alloc(sizeof(dhcp_service_class_t));
00121         if (dhcp_service) {
00122             ns_list_init(&dhcp_service->srv_list);
00123             ns_list_init(&dhcp_service->tr_list);
00124             dhcp_service->dhcp_client_socket = -1;
00125             dhcp_service->dhcp_server_socket = -1;
00126             dhcp_service->dhcpv6_socket_service_tasklet = eventOS_event_handler_create(DHCPv6_socket_service_tasklet, DHCPV6_SOCKET_SERVICE_TASKLET_INIT);
00127             if (dhcp_service->dhcpv6_socket_service_tasklet < 0) {
00128                 ns_dyn_mem_free(dhcp_service);
00129                 dhcp_service = NULL;
00130             } else {
00131                 retVal = true;
00132             }
00133         }
00134     } else {
00135         retVal = true;
00136     }
00137     return retVal;
00138 }
00139 
00140 /*Subclass instances*/
00141 msg_tr_t *dhcp_tr_find(uint32_t msg_tr_id)
00142 {
00143     msg_tr_t *result = NULL;
00144     ns_list_foreach(msg_tr_t, cur_ptr, &dhcp_service->tr_list) {
00145         if (cur_ptr->msg_tr_id == msg_tr_id) {
00146             result = cur_ptr;
00147         }
00148     }
00149     return result;
00150 }
00151 
00152 
00153 msg_tr_t *dhcp_tr_create(void)
00154 {
00155     uint32_t tr_id;
00156     msg_tr_t *msg_ptr = NULL;
00157     msg_ptr = ns_dyn_mem_temporary_alloc(sizeof(msg_tr_t));
00158     if (msg_ptr == NULL) {
00159         return NULL;
00160     }
00161 
00162     memset(msg_ptr, 0, sizeof(msg_tr_t));
00163     msg_ptr->msg_ptr = NULL;
00164     msg_ptr->recv_resp_cb = NULL;
00165 
00166     tr_id = randLIB_get_32bit() & 0xffffff;// 24 bits for random
00167     // Ensure a unique non-zero transaction id for each transaction
00168     while (tr_id == 0 || dhcp_tr_find(tr_id) != NULL) {
00169         tr_id = (tr_id + 1) & 0xffffff;
00170     }
00171     msg_ptr->msg_tr_id = tr_id;
00172     ns_list_add_to_start(&dhcp_service->tr_list, msg_ptr);
00173     return msg_ptr;
00174 }
00175 
00176 void dhcp_tr_delete(msg_tr_t *msg_ptr)
00177 {
00178     if (msg_ptr != NULL) {
00179         ns_list_remove(&dhcp_service->tr_list, msg_ptr);
00180         ns_dyn_mem_free(msg_ptr->msg_ptr);
00181         ns_dyn_mem_free(msg_ptr);
00182     }
00183     return;
00184 }
00185 
00186 void dhcp_tr_set_retry_timers(msg_tr_t *msg_ptr, uint8_t msg_type)
00187 {
00188     if (msg_ptr != NULL) {
00189         if (msg_type == DHCPV6_SOLICATION_TYPE) {
00190             msg_ptr->timeout_init = SOL_TIMEOUT;
00191             msg_ptr->timeout_max = SOL_MAX_RT;
00192             msg_ptr->retrans_max = 0;
00193         } else if (msg_type == DHCPV6_RENEW_TYPE) {
00194             msg_ptr->timeout_init = REN_TIMEOUT;
00195             msg_ptr->timeout_max = REN_MAX_RT;
00196             msg_ptr->retrans_max = 0;
00197         } else if (msg_type == DHCPV6_LEASEQUERY_TYPE) {
00198             msg_ptr->timeout_init = LQ_TIMEOUT;
00199             msg_ptr->timeout_max = LQ_MAX_RT;
00200             msg_ptr->retrans_max = LQ_MAX_RC;
00201         } else {
00202             msg_ptr->timeout_init = REL_TIMEOUT;
00203             msg_ptr->timeout_max = 0;
00204             msg_ptr->retrans_max = REL_MAX_RC;
00205         }
00206 
00207         // Convert from seconds to 1/10s ticks, with initial randomisation factor
00208         msg_ptr->timeout_init = randLIB_randomise_base(msg_ptr->timeout_init * 10, RAND1_LOW, RAND1_HIGH);
00209         msg_ptr->timeout_max *= 10;
00210 
00211         msg_ptr->timeout = msg_ptr->timeout_init;
00212         if (!dhcpv6_socket_timeout_timer_active) {
00213             eventOS_event_timer_request(DHCPV6_SOCKET_SERVICE_TIMER_ID, DHCPV6_SOCKET_SERVICE_TIMER, dhcp_service->dhcpv6_socket_service_tasklet, DHCPV6_SOCKET_TIMER_UPDATE_PERIOD_IN_MS);
00214             dhcpv6_socket_timeout_timer_active = true;
00215         }
00216     }
00217     return;
00218 }
00219 
00220 server_instance_t *dhcp_service_client_find(uint16_t instance_id)
00221 {
00222     server_instance_t *result = NULL;
00223     ns_list_foreach(server_instance_t, cur_ptr, &dhcp_service->srv_list) {
00224         if (cur_ptr->instance_id == instance_id) {
00225             result = cur_ptr;
00226         }
00227     }
00228     return result;
00229 }
00230 
00231 
00232 void recv_dhcp_server_msg(void *cb_res)
00233 {
00234     socket_callback_t *sckt_data;
00235     server_instance_t *srv_ptr = NULL;
00236     msg_tr_t *msg_tr_ptr;
00237     uint8_t *msg_ptr;
00238     uint16_t msg_len;
00239 
00240     sckt_data = cb_res;
00241 
00242     if (sckt_data->event_type != SOCKET_DATA || sckt_data->d_len < 4) {
00243         return;
00244     }
00245     tr_debug("dhcp Server recv request");
00246     msg_tr_ptr = dhcp_tr_create();
00247     msg_ptr = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
00248     if (msg_ptr == NULL || msg_tr_ptr == NULL) {
00249         // read actual message
00250         tr_error("Out of resources");
00251         goto cleanup;
00252     }
00253     msg_len = socket_read(sckt_data->socket_id, &msg_tr_ptr->addr, msg_ptr, sckt_data->d_len);
00254     //TODO use real function from lib also call validity check
00255     msg_tr_ptr->message_tr_id = common_read_24_bit(&msg_ptr[1]);
00256 
00257     if (0 != libdhcpv6_message_malformed_check(msg_ptr, msg_len)) {
00258         tr_error("Malformed packet");
00259         goto cleanup;
00260     }
00261     msg_tr_ptr->socket = sckt_data->socket_id;
00262     // call all receivers until found.
00263     ns_list_foreach(server_instance_t, cur_ptr, &dhcp_service->srv_list) {
00264         if (cur_ptr->interface_id == sckt_data->interface_id && cur_ptr->recv_req_cb != NULL) {
00265             msg_tr_ptr->instance_id = cur_ptr->instance_id;
00266             msg_tr_ptr->interface_id = sckt_data->interface_id;
00267             if ((RET_MSG_ACCEPTED ==
00268                     cur_ptr->recv_req_cb(cur_ptr->instance_id, msg_tr_ptr->msg_tr_id, *msg_ptr, msg_ptr + 4, msg_len - 4))) {
00269                 // should not modify pointers but library requires.
00270                 msg_tr_ptr = NULL;
00271                 srv_ptr = cur_ptr;
00272                 break;
00273             }
00274         }
00275     }
00276 
00277 cleanup:
00278     dhcp_tr_delete(msg_tr_ptr);
00279     ns_dyn_mem_free(msg_ptr);
00280     if (srv_ptr == NULL) {
00281         //no owner found
00282         tr_warn("No handler for this message found");
00283     }
00284 
00285     return;
00286 }
00287 
00288 void recv_dhcp_client_msg(void *cb_res)
00289 {
00290     ns_address_t address;
00291     socket_callback_t *sckt_data;
00292     msg_tr_t *msg_tr_ptr = NULL;
00293     uint8_t *msg_ptr = NULL;
00294     int16_t msg_len = 0;
00295     uint_fast24_t tr_id = 0;
00296     int retVal = RET_MSG_ACCEPTED;
00297 
00298     sckt_data = cb_res;
00299 
00300     if (sckt_data->event_type != SOCKET_DATA || sckt_data->d_len < 4) {
00301         return;
00302     }
00303     tr_debug("dhcp recv response message");
00304     // read actual message
00305     msg_ptr = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
00306 
00307     if (msg_ptr == NULL) {
00308         tr_error("Out of memory");
00309         goto cleanup;
00310     }
00311     msg_len = socket_read(sckt_data->socket_id, &address, msg_ptr, sckt_data->d_len);
00312 
00313     tr_id = common_read_24_bit(&msg_ptr[1]);
00314     msg_tr_ptr = dhcp_tr_find(tr_id);
00315 
00316     if (msg_tr_ptr == NULL) {
00317         tr_error("invalid tr id");
00318         goto cleanup;
00319     }
00320     if (0 != libdhcpv6_message_malformed_check(msg_ptr, msg_len)) {
00321         msg_tr_ptr->recv_resp_cb(msg_tr_ptr->instance_id, msg_tr_ptr->client_obj_ptr, 0, NULL, 0);
00322         tr_error("Malformed packet");
00323         goto cleanup;
00324     }
00325     // read msg tr id from message and find transaction. and then instance
00326     // TODO use real function from dhcp lib
00327 
00328     if (msg_tr_ptr != NULL && msg_tr_ptr->recv_resp_cb) {
00329         // call receive callback should not modify pointers but library requires
00330         retVal = msg_tr_ptr->recv_resp_cb(msg_tr_ptr->instance_id, msg_tr_ptr->client_obj_ptr, *msg_ptr, msg_ptr + 4, msg_len - 4);
00331     } else {
00332         tr_error("no receiver for this message found");
00333     }
00334 
00335 cleanup:
00336     ns_dyn_mem_free(msg_ptr);
00337     if (retVal != RET_MSG_WAIT_ANOTHER) {
00338         //Transaction is not killed yet
00339         dhcp_tr_delete(dhcp_tr_find(tr_id));
00340     }
00341     return ;
00342 }
00343 
00344 uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb)
00345 {
00346     uint16_t id = 1;
00347     server_instance_t *srv_ptr;
00348 
00349     if (!dhcp_service_allocate()) {
00350         tr_error("dhcp Sockets data base alloc fail");
00351         return 0;
00352     }
00353     if (instance_type == DHCP_INSTANCE_SERVER && dhcp_service->dhcp_server_socket < 0) {
00354         dhcp_service->dhcp_server_socket = socket_open(SOCKET_UDP, DHCPV6_SERVER_PORT, recv_dhcp_server_msg);
00355     }
00356     if (instance_type == DHCP_INSTANCE_CLIENT && dhcp_service->dhcp_client_socket < 0) {
00357         dhcp_service->dhcp_client_socket = socket_open(SOCKET_UDP, DHCPV6_CLIENT_PORT, recv_dhcp_client_msg);
00358     }
00359     if (instance_type == DHCP_INSTANCE_SERVER && dhcp_service->dhcp_server_socket < 0) {
00360         tr_error("No sockets available for DHCP server");
00361         return 0;
00362     }
00363     if (instance_type == DHCP_INSTANCE_CLIENT && dhcp_service->dhcp_client_socket < 0) {
00364         tr_error("No sockets available for DHCP client");
00365         return 0;
00366     }
00367     for (; id < MAX_SERVERS; id++) {
00368         if (dhcp_service_client_find(id) == NULL) {
00369             break;
00370         }
00371     }
00372     srv_ptr = ns_dyn_mem_temporary_alloc(sizeof(server_instance_t));
00373     if (id == MAX_SERVERS || srv_ptr == NULL) {
00374         tr_error("Out of server instances");
00375         ns_dyn_mem_free(srv_ptr);
00376         return 0;
00377     }
00378     ns_list_add_to_start(&dhcp_service->srv_list, srv_ptr);
00379     srv_ptr->instance_id = id;
00380     srv_ptr->instance_type = instance_type;
00381     srv_ptr->interface_id = interface_id;
00382     srv_ptr->recv_req_cb = receive_req_cb;
00383     return srv_ptr->instance_id;
00384 }
00385 
00386 void dhcp_service_delete(uint16_t instance)
00387 {
00388     server_instance_t *srv_ptr;
00389     if (dhcp_service == NULL) {
00390         return;
00391     }
00392     srv_ptr = dhcp_service_client_find(instance);
00393     //TODO delete all transactions
00394     if (srv_ptr != NULL) {
00395         ns_list_remove(&dhcp_service->srv_list, srv_ptr);
00396         ns_dyn_mem_free(srv_ptr);
00397     }
00398     ns_list_foreach_safe(msg_tr_t, cur_ptr, &dhcp_service->tr_list) {
00399         if (cur_ptr->instance_id == instance) {
00400             dhcp_tr_delete(cur_ptr);
00401         }
00402     }
00403 
00404     int8_t server_instances = 0, client_instances = 0;
00405 
00406     ns_list_foreach(server_instance_t, srv, &dhcp_service->srv_list) {
00407         if (srv->instance_type == DHCP_INSTANCE_SERVER) {
00408             ++server_instances;
00409         } else if (srv->instance_type == DHCP_INSTANCE_CLIENT) {
00410             ++client_instances;
00411         }
00412     }
00413 
00414     if (server_instances == 0 && dhcp_service->dhcp_server_socket > -1) {
00415         socket_close(dhcp_service->dhcp_server_socket);
00416         dhcp_service->dhcp_server_socket = -1;
00417     }
00418 
00419     if (client_instances == 0 && dhcp_service->dhcp_client_socket > -1) {
00420         socket_close(dhcp_service->dhcp_client_socket);
00421         dhcp_service->dhcp_client_socket = -1;
00422     }
00423     return;
00424 }
00425 
00426 int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len)
00427 {
00428     msg_tr_t *msg_tr_ptr;
00429     server_instance_t *srv_instance;
00430     msg_tr_ptr = dhcp_tr_find(msg_tr_id);
00431     if (msg_tr_ptr == NULL) {
00432         tr_error("msg_tr_id not found");
00433         return -1;
00434     }
00435     srv_instance = dhcp_service_client_find(msg_tr_ptr->instance_id);
00436     if (srv_instance == NULL) {
00437         tr_error("Srv Instance not found");
00438         return -1;
00439     }
00440     ns_dyn_mem_free(msg_tr_ptr->msg_ptr);
00441 
00442     msg_tr_ptr->msg_ptr = msg_ptr;
00443     msg_tr_ptr->msg_len = msg_len;
00444     msg_tr_ptr->options = options;
00445     // set the received transaction id to message.
00446     common_write_24_bit(msg_tr_ptr->message_tr_id, &msg_tr_ptr->msg_ptr[1]);
00447 
00448     dhcp_service_send_message(msg_tr_ptr);
00449     msg_tr_ptr->msg_ptr = NULL; // pointer is the responsibility of client
00450     dhcp_tr_delete(msg_tr_ptr);
00451     return 0;
00452 }
00453 uint32_t dhcp_service_send_req(uint16_t instance_id, uint8_t options, void *ptr, const uint8_t addr[static 16], uint8_t *msg_ptr, uint16_t msg_len, dhcp_service_receive_resp_cb *receive_resp_cb)
00454 {
00455     msg_tr_t *msg_tr_ptr;
00456     server_instance_t *srv_ptr;
00457     srv_ptr = dhcp_service_client_find(instance_id);
00458     msg_tr_ptr = dhcp_tr_create();
00459 
00460     if (msg_tr_ptr == NULL || srv_ptr == NULL || msg_ptr == NULL || receive_resp_cb == NULL || msg_len < 5) {
00461         tr_error("request sending failed");
00462         return 0;
00463     }
00464 
00465     msg_tr_ptr->msg_ptr = msg_ptr;
00466     msg_tr_ptr->msg_len = msg_len;
00467     msg_tr_ptr->options = options;
00468     msg_tr_ptr->client_obj_ptr = ptr;
00469     memcpy(msg_tr_ptr->addr.address, addr, 16);
00470     msg_tr_ptr->addr.identifier = DHCPV6_SERVER_PORT;
00471     msg_tr_ptr->addr.type = ADDRESS_IPV6;
00472     msg_tr_ptr->interface_id = srv_ptr->interface_id;
00473     msg_tr_ptr->instance_id = instance_id;
00474     msg_tr_ptr->socket = dhcp_service->dhcp_client_socket;
00475     msg_tr_ptr->recv_resp_cb = receive_resp_cb;
00476     msg_tr_ptr->first_transmit_time = protocol_core_monotonic_time;
00477     dhcp_tr_set_retry_timers(msg_tr_ptr, msg_tr_ptr->msg_ptr[0]);
00478     common_write_24_bit(msg_tr_ptr->msg_tr_id, &msg_tr_ptr->msg_ptr[1]);
00479 
00480     dhcp_service_send_message(msg_tr_ptr);
00481     return msg_tr_ptr->msg_tr_id;
00482 }
00483 
00484 void dhcp_service_set_retry_timers(uint32_t msg_tr_id, uint16_t timeout_init, uint16_t timeout_max, uint8_t retrans_max)
00485 {
00486     msg_tr_t *msg_tr_ptr;
00487     msg_tr_ptr = dhcp_tr_find(msg_tr_id);
00488 
00489     if (msg_tr_ptr != NULL) {
00490         msg_tr_ptr->timeout_init = randLIB_randomise_base(timeout_init * 10, RAND1_LOW, RAND1_HIGH);
00491         msg_tr_ptr->timeout = msg_tr_ptr->timeout_init;
00492         msg_tr_ptr->timeout_max = timeout_max * 10;
00493         msg_tr_ptr->retrans_max = retrans_max;
00494     }
00495     return;
00496 }
00497 
00498 void dhcp_service_req_remove(uint32_t msg_tr_id)
00499 {
00500     if (dhcp_service) {
00501         dhcp_tr_delete(dhcp_tr_find(msg_tr_id));
00502     }
00503     return;
00504 }
00505 
00506 void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
00507 {
00508     int8_t retval;
00509     int16_t multicast_hop_limit = -1;
00510     const uint32_t address_pref = SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT;
00511     dhcp_options_msg_t elapsed_time;
00512 
00513     if (libdhcpv6_message_option_discover((msg_tr_ptr->msg_ptr + 4), (msg_tr_ptr->msg_len -4), DHCPV6_ELAPSED_TIME_OPTION, &elapsed_time) == 0 &&
00514             elapsed_time.len == 2) {
00515         uint32_t t = protocol_core_monotonic_time - msg_tr_ptr->first_transmit_time; // time in 1/10s ticks
00516         uint16_t cs;
00517         if (t > 0xffff / 10) {
00518             cs = 0xffff;
00519         } else {
00520             cs = (uint16_t) t * 10;
00521         }
00522         common_write_16_bit(cs, elapsed_time.msg_ptr);
00523     }
00524 
00525     if ((msg_tr_ptr->options & TX_OPT_USE_SHORT_ADDR) == TX_OPT_USE_SHORT_ADDR) {
00526         socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_ADDR_PREFERENCES, &address_pref, sizeof address_pref);
00527     }
00528     if ((msg_tr_ptr->options & TX_OPT_MULTICAST_HOP_LIMIT_64) == TX_OPT_MULTICAST_HOP_LIMIT_64) {
00529         multicast_hop_limit = 64;
00530     }
00531     socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, &multicast_hop_limit, sizeof multicast_hop_limit);
00532     socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_INTERFACE_SELECT, &msg_tr_ptr->interface_id, sizeof(int8_t));
00533     retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len);
00534     if (retval != 0) {
00535         tr_warn("dhcp service socket_sendto fails: %i", retval);
00536     }
00537 }
00538 bool dhcp_service_timer_tick(uint16_t ticks)
00539 {
00540     bool activeTimerNeed = false;
00541     ns_list_foreach_safe(msg_tr_t, cur_ptr, &dhcp_service->tr_list) {
00542         if (cur_ptr->timeout == 0) {
00543             continue;
00544         }
00545 
00546         if (cur_ptr->timeout <= ticks) {
00547             activeTimerNeed = true;
00548             cur_ptr->retrans++;
00549             if (cur_ptr->retrans_max != 0 && cur_ptr->retrans >= cur_ptr->retrans_max) {
00550                 // retransmission count exceeded.
00551                 cur_ptr->recv_resp_cb(cur_ptr->instance_id, cur_ptr->client_obj_ptr, 0, NULL, 0);
00552                 dhcp_tr_delete(cur_ptr);
00553                 continue;
00554             }
00555             dhcp_service_send_message(cur_ptr);
00556             // RFC 3315 says:
00557             //     RT = 2*RTprev + RAND*RTprev,
00558             // We calculate this as
00559             //     RT = RTprev + (1+RAND)*RTprev
00560             cur_ptr->timeout = cur_ptr->timeout_init + randLIB_randomise_base(cur_ptr->timeout_init, RAND1_LOW, RAND1_HIGH);
00561             // Catch 16-bit integer overflow
00562             if (cur_ptr->timeout < cur_ptr->timeout_init) {
00563                 cur_ptr->timeout = 0xFFFF;
00564             }
00565             // Check against MRT
00566             if (cur_ptr->timeout_max != 0 && cur_ptr->timeout > cur_ptr->timeout_max) {
00567                 cur_ptr->timeout = randLIB_randomise_base(cur_ptr->timeout_max, RAND1_LOW, RAND1_HIGH);
00568             }
00569             cur_ptr->timeout_init = cur_ptr->timeout;
00570         } else {
00571             cur_ptr->timeout -= ticks;
00572             activeTimerNeed = true;
00573         }
00574     }
00575     return activeTimerNeed;
00576 }
00577 #else
00578 uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb)
00579 {
00580     (void)interface_id;
00581     (void)instance_type;
00582     (void)receive_req_cb;
00583     return 0;
00584 }
00585 
00586 void dhcp_service_delete(uint16_t instance)
00587 {
00588     (void)instance;
00589 }
00590 
00591 int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len)
00592 {
00593     (void)msg_tr_id;
00594     (void)options;
00595     (void)msg_ptr;
00596     (void)msg_len;
00597     return -1;
00598 }
00599 
00600 uint32_t dhcp_service_send_req(uint16_t instance_id, uint8_t options, void *ptr, const uint8_t addr[static 16], uint8_t *msg_ptr, uint16_t msg_len, dhcp_service_receive_resp_cb *receive_resp_cb)
00601 {
00602     (void)instance_id;
00603     (void)options;
00604     (void)ptr;
00605     (void)addr;
00606     (void)msg_ptr;
00607     (void)msg_len;
00608     (void)receive_resp_cb;
00609     return 0;
00610 }
00611 
00612 void dhcp_service_set_retry_timers(uint32_t msg_tr_id, uint16_t timeout_init, uint16_t timeout_max, uint8_t retrans_max)
00613 {
00614     (void)msg_tr_id;
00615     (void)timeout_init;
00616     (void)timeout_max;
00617     (void)retrans_max;
00618 }
00619 void dhcp_service_req_remove(uint32_t msg_tr_id)
00620 {
00621     (void)msg_tr_id;
00622 }
00623 
00624 bool dhcp_service_timer_tick(uint16_t ticks)
00625 {
00626     (void)ticks;
00627     return false;
00628 }
00629 #endif