Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 18:18:31 by
