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.
Fork of OmniWheels by
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 Fri Jul 22 2022 04:53:47 by
1.7.2
