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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
DHCPv6_Server_service.c
00001 /* 00002 * Copyright (c) 2014-2018, 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 /* 00019 * \file DHCPv6_Server_service.c 00020 * \brief Add short description about this file!!! 00021 * 00022 */ 00023 #include "nsconfig.h" 00024 #ifdef HAVE_DHCPV6_SERVER 00025 #include <string.h> 00026 #include <ns_types.h> 00027 #include <ns_trace.h> 00028 #include "eventOS_event.h" 00029 #include "eventOS_scheduler.h" 00030 #include "eventOS_event_timer.h" 00031 #include <nsdynmemLIB.h> 00032 #include "libDHCPv6/libDHCPv6.h" 00033 #include "libDHCPv6/libDHCPv6_server.h" 00034 #include "DHCPv6_Server/DHCPv6_server_service.h" 00035 #include "common_functions.h" 00036 #include "NWK_INTERFACE/Include/protocol.h" 00037 #include "Common_Protocols/icmpv6.h" 00038 #include "dhcp_service_api.h" 00039 00040 #define TRACE_GROUP "dhcp" 00041 00042 #define DHCPV6_GUA_IF "dhcp" 00043 #define DHCPV6_SERVER_SERVICE_TASKLET_INIT 1 00044 #define DHCPV6_SERVER_SERVICE_TIMER 2 00045 00046 #define DHCPV6_SERVER_SERVICE_TIMER_ID 1 00047 00048 #define DHCPV6_TIMER_UPDATE_PERIOD_IN_SECONDS 10 00049 00050 typedef struct dhcpv6_gua_response { 00051 uint16_t responseLength; 00052 uint8_t *responsePtr; 00053 } dhcpv6_gua_response_t; 00054 00055 static int8_t dhcpv6_service_tasklet = -1; 00056 00057 static arm_event_storage_t *dhcp_timer_storage = NULL; 00058 00059 static bool DHCP_server_service_timer_start(void) 00060 { 00061 if (!dhcp_timer_storage) { 00062 arm_event_s event = { 00063 .receiver = dhcpv6_service_tasklet, 00064 .sender = 0, 00065 .event_id = DHCPV6_SERVER_SERVICE_TIMER_ID, 00066 .data_ptr = NULL, 00067 .event_type = DHCPV6_SERVER_SERVICE_TIMER, 00068 .priority = ARM_LIB_LOW_PRIORITY_EVENT, 00069 }; 00070 00071 dhcp_timer_storage = eventOS_event_timer_request_every(&event, eventOS_event_timer_ms_to_ticks(DHCPV6_TIMER_UPDATE_PERIOD_IN_SECONDS * 1000)); 00072 if (!dhcp_timer_storage) { 00073 tr_error("Dhcp server timer start fail"); 00074 return false; 00075 } 00076 } 00077 return true; 00078 } 00079 00080 static void DHCP_server_service_timer_stop(void) 00081 { 00082 if (dhcp_timer_storage && libdhcpv6_gua_server_list_empty()) { 00083 eventOS_cancel(dhcp_timer_storage); 00084 dhcp_timer_storage = NULL; 00085 } 00086 } 00087 00088 int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_reply_packet_s *replyPacket, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, dhcpv6_gua_response_t *response, bool allocateNew) 00089 { 00090 dhcpv6_alloacted_address_entry_t *dhcp_allocated_address = NULL; 00091 dhcpv6_ia_non_temporal_address_s nonTemporalAddress; 00092 bool address_allocated = false; 00093 //Validate Client DUID 00094 dhcp_link_options_params_t clientDUID; 00095 if (libdhcpv6_get_link_address_from_duid(replyPacket->clientDUID.duid, replyPacket->clientDUID.duid_length, replyPacket->clientDUID.type, &clientDUID) == 0) { 00096 dhcp_allocated_address = libdhcpv6_address_allocated_list_scan(serverBase, clientDUID.link_id, clientDUID.link_type, dhcp_ia_non_temporal_params->iaId, dhcp_ia_non_temporal_params->T0, dhcp_ia_non_temporal_params->T1, allocateNew); 00097 } 00098 if (dhcp_allocated_address) { 00099 address_allocated = true; 00100 nonTemporalAddress.requestedAddress = dhcp_allocated_address->nonTemporalAddress; 00101 nonTemporalAddress.validLifeTime = dhcp_allocated_address->lifetime; 00102 nonTemporalAddress.preferredLifeTime = dhcp_allocated_address->preferredLifetime; 00103 00104 if (serverBase->addCb) { 00105 dhcp_address_cache_update_t update_info; 00106 update_info.allocatedAddress = dhcp_allocated_address->nonTemporalAddress; 00107 update_info.allocatedNewAddress = allocateNew; 00108 update_info.validLifeTime = nonTemporalAddress.validLifeTime; 00109 00110 if (!serverBase->addCb(serverBase->interfaceId, &update_info, serverBase->guaPrefix)) { 00111 address_allocated = false; 00112 libdhcpv6_address_rm_from_allocated_list(serverBase, dhcp_allocated_address->nonTemporalAddress); 00113 } 00114 } 00115 } 00116 00117 response->responseLength = libdhcpv6_address_reply_message_len(replyPacket->clientDUID.duid_length, replyPacket->serverDUID.duid_length, 0, replyPacket->rapidCommit, address_allocated); 00118 response->responsePtr = ns_dyn_mem_temporary_alloc(response->responseLength); 00119 if (response->responsePtr) { 00120 if (address_allocated) { 00121 libdhcpv6_reply_message_write(response->responsePtr, replyPacket, &nonTemporalAddress, NULL); 00122 } else { 00123 libdhcpv6_reply_message_write(response->responsePtr, replyPacket, NULL, NULL); 00124 } 00125 return 0; 00126 } 00127 return -1; 00128 } 00129 00130 00131 int DHCPV6_server_service_request_handler(uint16_t instance_id, uint32_t msg_tr_id, uint8_t message_type, uint8_t *msg_ptr, uint16_t msg_len) 00132 { 00133 int retVal = RET_MSG_NOT_MINE; 00134 dhcp_ia_non_temporal_params_t dhcp_ia_non_temporal_params; 00135 dhcpv6_reply_packet_s replyPacket; 00136 dhcpv6_gua_response_t responseBuf; 00137 dhcpv6_gua_server_entry_s *serverBase; 00138 00139 tr_debug("GUA Handler"); 00140 switch (message_type) { 00141 case DHCPV6_SOLICATION_TYPE: 00142 if (libdhcpv6_solication_message_options_validate(msg_ptr, msg_len, &replyPacket.clientDUID, &dhcp_ia_non_temporal_params) == 0) { 00143 //Start Build Response 00144 serverBase = libdhcpv6_server_data_get_by_prefix_and_socketinstance(instance_id, dhcp_ia_non_temporal_params.nonTemporalAddress); 00145 if (serverBase) { 00146 //Here Allocate address 00147 replyPacket.rapidCommit = libdhcpv6_rapid_commit_option_at_packet(msg_ptr, msg_len); 00148 replyPacket.serverDUID = serverBase->serverDUID; 00149 replyPacket.T0 = dhcp_ia_non_temporal_params.T0; 00150 replyPacket.T1 = dhcp_ia_non_temporal_params.T1; 00151 replyPacket.iaId = dhcp_ia_non_temporal_params.iaId; 00152 replyPacket.transaction_ID = msg_tr_id; 00153 00154 tr_debug("Response dhcp sol %s clientDUID", trace_array(replyPacket.clientDUID.duid, replyPacket.clientDUID.duid_length)); 00155 00156 //Check First Current list 00157 if (DHCPv6_server_respond_client(serverBase, &replyPacket, &dhcp_ia_non_temporal_params, &responseBuf, true) == 0) { 00158 //Respond 00159 dhcp_service_send_resp(msg_tr_id, TX_OPT_NONE, responseBuf.responsePtr, responseBuf.responseLength); 00160 ns_dyn_mem_free(responseBuf.responsePtr); 00161 retVal = RET_MSG_ACCEPTED; 00162 } 00163 00164 } 00165 } 00166 break; 00167 00168 case DHCPV6_RELEASE_TYPE: 00169 00170 break; 00171 00172 case DHCPV6_RENEW_TYPE: 00173 if (libdhcpv6_renew_message_options_validate(msg_ptr, msg_len, &replyPacket.clientDUID, &replyPacket.serverDUID, &dhcp_ia_non_temporal_params) == 0) { 00174 // Discover SERVER 00175 serverBase = libdhcpv6_server_data_get_by_prefix_and_socketinstance(instance_id, dhcp_ia_non_temporal_params.nonTemporalAddress); 00176 if (serverBase) { 00177 if (libdhcpv6_compare_DUID(&serverBase->serverDUID, &replyPacket.serverDUID) == 0) { 00178 replyPacket.rapidCommit = libdhcpv6_rapid_commit_option_at_packet(msg_ptr, msg_len); 00179 replyPacket.T0 = dhcp_ia_non_temporal_params.T0; 00180 replyPacket.T1 = dhcp_ia_non_temporal_params.T1; 00181 replyPacket.iaId = dhcp_ia_non_temporal_params.iaId; 00182 replyPacket.transaction_ID = msg_tr_id; 00183 //Check First Current list 00184 if (DHCPv6_server_respond_client(serverBase, &replyPacket, &dhcp_ia_non_temporal_params, &responseBuf, false) == 0) { 00185 //Respond 00186 dhcp_service_send_resp(msg_tr_id, TX_OPT_NONE, responseBuf.responsePtr, responseBuf.responseLength); 00187 ns_dyn_mem_free(responseBuf.responsePtr); 00188 retVal = RET_MSG_ACCEPTED; 00189 } 00190 } 00191 00192 } 00193 } 00194 break; 00195 00196 default: 00197 tr_warn("UnSupported MessageId: %02x", message_type); 00198 } 00199 return retVal; 00200 } 00201 00202 00203 void DHCPv6_server_service_tasklet(arm_event_s *event) 00204 { 00205 if (event->event_type == DHCPV6_SERVER_SERVICE_TASKLET_INIT) { 00206 //We should define peridiocally timer service!! 00207 } else if (event->event_type == DHCPV6_SERVER_SERVICE_TIMER) { 00208 libdhcpv6_gua_servers_time_update(DHCPV6_TIMER_UPDATE_PERIOD_IN_SECONDS); 00209 } 00210 } 00211 00212 static int8_t dhcpv6_server_service_tasklet_generated(void) 00213 { 00214 if (dhcpv6_service_tasklet == -1) { 00215 dhcpv6_service_tasklet = eventOS_event_handler_create(DHCPv6_server_service_tasklet, DHCPV6_SERVER_SERVICE_TASKLET_INIT); 00216 } 00217 00218 return dhcpv6_service_tasklet; 00219 } 00220 00221 /* Initialize dhcp Global address server. 00222 * 00223 * This instance needs to bee initialized once for each thread network interface. 00224 * if only one thread instance is supported this is needed to call only once. 00225 * 00226 * /param interface interface id of this thread instance. 00227 * /param guaPrefix Global prefix /64 00228 * /param serverDUID Server Device ID (64-bit MAC) 00229 * /param serverDUIDType 00230 * 00231 */ 00232 int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType) 00233 { 00234 int retVal = -1; 00235 uint16_t socketInstance; 00236 protocol_interface_info_entry_t *cur; 00237 (void)serverDUID; 00238 //allocate Socket Service 00239 socketInstance = dhcp_service_init(interface, DHCP_INSTANCE_SERVER, DHCPV6_server_service_request_handler); 00240 cur = protocol_stack_interface_info_get_by_id(interface); 00241 if (!cur) { 00242 return -1; 00243 } 00244 00245 if (dhcpv6_server_service_tasklet_generated() < 0) { 00246 retVal = -2; 00247 } else if (!DHCP_server_service_timer_start()) { 00248 retVal = -2; 00249 } else { 00250 //allocate server 00251 dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_gua_server_allocate(guaPrefix, interface, cur->mac, serverDUIDType); 00252 if (serverInfo) { 00253 serverInfo->socketInstance_id = socketInstance; 00254 socketInstance = 0; 00255 retVal = 0; 00256 } 00257 } 00258 if (socketInstance > 0) { 00259 dhcp_service_delete(socketInstance); 00260 DHCP_server_service_timer_stop(); 00261 } 00262 return retVal; 00263 } 00264 00265 void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds) 00266 { 00267 libdhcpv6_gua_servers_time_update(timeUpdateInSeconds); 00268 } 00269 00270 /* Delete dhcp thread dhcp router ID server. 00271 * 00272 * When this is called it close selected service and free all allocated memory. 00273 * 00274 * /param interface interface id of this thread instance. 00275 * /param guaPrefix Prefix which will be removed 00276 * /param delete_gua_addresses Whether or not assigned addresses with the prefix should be removed from the interface. 00277 */ 00278 void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], bool delete_gua_addresses) 00279 { 00280 dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); 00281 if (serverInfo) { 00282 ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { 00283 //Delete Server data base 00284 if (serverInfo->removeCb) { 00285 serverInfo->removeCb(interface, cur->nonTemporalAddress, NULL); 00286 } 00287 } 00288 if (serverInfo->removeCb) { 00289 // Clean all /128 'Thread Proxy' routes to self and others added when acting as a DHCP server 00290 serverInfo->removeCb(interface, NULL, serverInfo->guaPrefix); 00291 } 00292 dhcp_service_delete(serverInfo->socketInstance_id); 00293 } 00294 00295 if (delete_gua_addresses) { 00296 protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interface); 00297 if (curPtr) { 00298 protocol_core_dhcpv6_allocated_address_remove(curPtr, guaPrefix); 00299 } 00300 } 00301 00302 libdhcpv6_gua_server_free_by_prefix_and_interfaceid(guaPrefix, interface); 00303 00304 DHCP_server_service_timer_stop(); 00305 00306 } 00307 00308 /* Control GUA address for client by DUI.Default value is true 00309 * 00310 * 00311 * /param interface interface id of this thread instance. 00312 * /param guaPrefix Prefix which will be removed 00313 * /param mode true trig autonous mode, false define address by default suffics + client id 00314 */ 00315 int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode) 00316 { 00317 int retVal = -1; 00318 dhcpv6_gua_server_entry_s *serverInfo; 00319 00320 serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); 00321 if (serverInfo) { 00322 serverInfo->enableAddressAutonous = mode; 00323 retVal = 0; 00324 } 00325 00326 return retVal; 00327 } 00328 00329 void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb) 00330 { 00331 dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); 00332 if (!serverInfo) { 00333 return; 00334 } 00335 00336 serverInfo->addCb = add_cb; 00337 serverInfo->removeCb = remove_cb; 00338 } 00339 00340 00341 int DHCPv6_server_service_duid_update(int8_t interface, uint8_t guaPrefix[static 16], uint8_t *duid_ptr, uint16_t duid_type, uint8_t duid_length) 00342 { 00343 00344 //Validate length and type 00345 if (!libdhcpv6_duid_length_validate(duid_type, duid_length)) { 00346 return -1; 00347 } 00348 00349 00350 dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); 00351 if (!serverInfo) { 00352 return -1; 00353 } 00354 00355 return libdhcpv6_server_duid_set(serverInfo, duid_ptr, duid_type, duid_length); 00356 } 00357 00358 00359 /* SET max accepted clients to server, Default is 200 00360 * 00361 * 00362 * /param interface interface id of this thread instance. 00363 * /param guaPrefix Prefix which will be removed 00364 * /param maxClientCount 00365 */ 00366 int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_t guaPrefix[static 16], uint32_t maxClientCount) 00367 { 00368 int retVal = -1; 00369 dhcpv6_gua_server_entry_s *serverInfo; 00370 if (maxClientCount == 0) { 00371 return -2; 00372 } else { 00373 serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); 00374 if (serverInfo) { 00375 serverInfo->maxSuppertedClients = maxClientCount; 00376 retVal = 0; 00377 } 00378 } 00379 return retVal; 00380 } 00381 00382 /** SET Address Valid Lifetime parameter for allocated address, Default is 7200 seconds 00383 * 00384 * 00385 * /param interface interface id of this thread instance. 00386 * /param guaPrefix Prefix which will be removed 00387 * /param validLifeTimne in seconds 00388 */ 00389 int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne) 00390 { 00391 int retVal = -1; 00392 dhcpv6_gua_server_entry_s *serverInfo; 00393 if (validLifeTimne < 120) { 00394 retVal = -2; 00395 } else { 00396 serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); 00397 if (serverInfo) { 00398 serverInfo->validLifetime = validLifeTimne; 00399 retVal = 0; 00400 } 00401 } 00402 return retVal; 00403 } 00404 #else 00405 00406 int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType) 00407 { 00408 (void) interface; 00409 (void) guaPrefix; 00410 (void) serverDUID; 00411 (void) serverDUIDType; 00412 00413 return -1; 00414 } 00415 void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], bool delete_gua_addresses) 00416 { 00417 (void) interface; 00418 (void) guaPrefix; 00419 (void) delete_gua_addresses; 00420 } 00421 void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds) 00422 { 00423 (void) timeUpdateInSeconds; 00424 } 00425 int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode) 00426 { 00427 (void) interface; 00428 (void) guaPrefix; 00429 (void) mode; 00430 00431 return -1; 00432 } 00433 int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_t guaPrefix[static 16], uint32_t maxClientCount) 00434 { 00435 (void) interface; 00436 (void) guaPrefix; 00437 (void) maxClientCount; 00438 00439 return -1; 00440 } 00441 int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne) 00442 { 00443 (void) interface; 00444 (void) guaPrefix; 00445 (void) validLifeTimne; 00446 00447 return -1; 00448 } 00449 00450 #endif
Generated on Tue Jul 12 2022 13:54:16 by
1.7.2