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
libDHCPv6_server.c
00001 /* 00002 * Copyright (c) 2014-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 /* 00019 * \file dhcpv6_server_api.c 00020 * \brief Add short description about this file!!! 00021 * 00022 */ 00023 #include "nsconfig.h" 00024 #include <string.h> 00025 #include <ns_types.h> 00026 #include <nsdynmemLIB.h> 00027 #include "libDHCPv6/libDHCPv6_server.h" 00028 #include "libDHCPv6/libDHCPv6.h" 00029 #include "common_functions.h" 00030 #include "ns_trace.h" 00031 00032 #ifdef HAVE_DHCPV6_SERVER 00033 00034 static NS_LARGE NS_LIST_DEFINE(dhcpv6_gua_server_list, dhcpv6_gua_server_entry_s, link); 00035 00036 bool libdhcpv6_gua_server_list_empty(void) 00037 { 00038 return ns_list_is_empty(&dhcpv6_gua_server_list); 00039 } 00040 00041 static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void) 00042 { 00043 dhcpv6_gua_server_entry_s *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_gua_server_entry_s)); 00044 uint8_t *server_duid_ptr = ns_dyn_mem_alloc(16);// Allocate 128-bit DUID-UUID by default it cover DUID-LL and DUID-LLTP also 00045 if (!entry || !server_duid_ptr) { 00046 ns_dyn_mem_free(entry); 00047 ns_dyn_mem_free(server_duid_ptr); 00048 return NULL; 00049 } 00050 entry->serverDynamic_DUID = server_duid_ptr; 00051 entry->serverDynamic_DUID_length = 16; 00052 entry->clientIdSequence = 0; 00053 entry->enableAddressAutonous = true; 00054 entry->clientIdDefaultSuffics = 0x0000000; 00055 entry->maxSuppertedClients = 200; 00056 entry->validLifetime = 7200; 00057 entry->removeCb = NULL; 00058 entry->addCb = NULL; 00059 ns_list_init(&entry->allocatedAddressList); 00060 return entry; 00061 } 00062 static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_alloacted_address_entry_t *entry) 00063 { 00064 //GENERATE ADDRESS 00065 uint8_t *ptr = entry->nonTemporalAddress; 00066 memcpy(ptr, serverInfo->guaPrefix, 8); 00067 ptr += 8; 00068 if (serverInfo->enableAddressAutonous) { 00069 if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || 00070 entry->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { 00071 memcpy(ptr, entry->linkId, 8); 00072 *ptr ^= 2; 00073 } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { 00074 *ptr++ = entry->linkId[0] ^ 2; 00075 *ptr++ = entry->linkId[1]; 00076 *ptr++ = entry->linkId[2]; 00077 *ptr++ = 0xff; 00078 *ptr++ = 0xfe; 00079 *ptr++ = entry->linkId[3]; 00080 *ptr++ = entry->linkId[4]; 00081 *ptr = entry->linkId[5]; 00082 } else { 00083 ptr = common_write_32_bit((serverInfo->clientIdDefaultSuffics | 02000000), ptr); 00084 ptr = common_write_32_bit((serverInfo->clientIdSequence + 2), ptr); 00085 } 00086 00087 } else { 00088 ptr = common_write_32_bit((serverInfo->clientIdDefaultSuffics | 02000000), ptr); 00089 ptr = common_write_32_bit((serverInfo->clientIdSequence + 2), ptr); 00090 } 00091 serverInfo->clientIdSequence++; 00092 } 00093 00094 00095 void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) 00096 { 00097 //Check All allocated server inside this loop 00098 ns_list_foreach(dhcpv6_gua_server_entry_s, cur, &dhcpv6_gua_server_list) { 00099 //Check All allocated address in this module 00100 ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, address, &cur->allocatedAddressList) { 00101 //Update 00102 if (address->preferredLifetime) { 00103 if (address->preferredLifetime <= timeUpdateInSeconds) { 00104 //Stop use this address for leasequery and delete Route or address map 00105 00106 address->preferredLifetime = 0; 00107 if (cur->removeCb) { 00108 cur->removeCb(cur->interfaceId, address->nonTemporalAddress, cur->guaPrefix); 00109 } 00110 } else { 00111 address->preferredLifetime -= timeUpdateInSeconds; 00112 } 00113 } 00114 00115 if (address->lifetime <= timeUpdateInSeconds) { 00116 ns_list_remove(&cur->allocatedAddressList, address); 00117 ns_dyn_mem_free(address); 00118 } else { 00119 address->lifetime -= timeUpdateInSeconds; 00120 } 00121 } 00122 } 00123 } 00124 00125 dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_interfaceid(int8_t interfaceId, const uint8_t *prefixPtr) 00126 { 00127 ns_list_foreach(dhcpv6_gua_server_entry_s, cur, &dhcpv6_gua_server_list) { 00128 if (cur->interfaceId == interfaceId) { 00129 if (memcmp(cur->guaPrefix, prefixPtr, 8) == 0) { 00130 return cur; 00131 } 00132 } 00133 } 00134 return NULL; 00135 } 00136 00137 dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstance(uint16_t socketInstance, uint8_t *prefixPtr) 00138 { 00139 ns_list_foreach(dhcpv6_gua_server_entry_s, cur, &dhcpv6_gua_server_list) { 00140 if (cur->socketInstance_id == socketInstance) { 00141 00142 if (!prefixPtr || memcmp(cur->guaPrefix, prefixPtr, 8) == 0) { 00143 return cur; 00144 } 00145 } 00146 } 00147 return NULL; 00148 } 00149 00150 int libdhcpv6_server_duid_set(dhcpv6_gua_server_entry_s *server_info, uint8_t *duid_ptr, uint16_t duid_type, uint8_t duid_length) 00151 { 00152 //Allocate dynamically new Server DUID if needed 00153 if (duid_length > server_info->serverDynamic_DUID_length) { 00154 //Allocate dynamic new bigger 00155 uint8_t *new_ptr = ns_dyn_mem_alloc(duid_length); 00156 if (!new_ptr) { 00157 return -1; 00158 } 00159 server_info->serverDynamic_DUID_length = duid_length; 00160 ns_dyn_mem_free(server_info->serverDynamic_DUID); 00161 server_info->serverDynamic_DUID = new_ptr; 00162 } 00163 //SET DUID 00164 server_info->serverDUID.duid = server_info->serverDynamic_DUID; 00165 memcpy(server_info->serverDUID.duid, duid_ptr, duid_length); 00166 server_info->serverDUID.duid_length = duid_length; 00167 server_info->serverDUID.type = duid_type; 00168 return 0; 00169 } 00170 00171 00172 dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType) 00173 { 00174 00175 00176 dhcpv6_gua_server_entry_s *entry = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix); 00177 if (entry == NULL) { 00178 entry = libdhcpv6_server_entry_allocate(); 00179 if (!entry) { 00180 return NULL; 00181 } 00182 //Generate Server DUID-LL by default 00183 uint8_t *ptr; 00184 uint8_t duid_ll[16]; 00185 uint8_t duid_length; 00186 ptr = duid_ll; 00187 duid_length = libdhcpv6_duid_linktype_size(serverDUIDType) + 2; 00188 ptr = common_write_16_bit(serverDUIDType, ptr); 00189 memcpy(ptr, serverDUID, libdhcpv6_duid_linktype_size(serverDUIDType)); 00190 00191 //SET DUID 00192 if (libdhcpv6_server_duid_set(entry, duid_ll, DHCPV6_DUID_LINK_LAYER_TYPE, duid_length) != 0) { 00193 ns_dyn_mem_free(entry->serverDynamic_DUID); 00194 ns_dyn_mem_free(entry); 00195 return NULL; 00196 } 00197 00198 00199 memcpy(entry->guaPrefix, prefix, 8); 00200 entry->interfaceId = interfaceId; 00201 ns_list_add_to_end(&dhcpv6_gua_server_list, entry); 00202 } 00203 return entry; 00204 } 00205 00206 void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId) 00207 { 00208 dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix); 00209 if (serverInfo) { 00210 if ((serverInfo->interfaceId == interfaceId) && (memcmp(serverInfo->guaPrefix, prefix, 8) == 0)) { 00211 ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { 00212 ns_list_remove(&serverInfo->allocatedAddressList, cur); 00213 ns_dyn_mem_free(cur); 00214 } 00215 ns_list_remove(&dhcpv6_gua_server_list, serverInfo); 00216 ns_dyn_mem_free(serverInfo->serverDynamic_DUID); 00217 ns_dyn_mem_free(serverInfo); 00218 } 00219 } 00220 } 00221 00222 static dhcpv6_alloacted_address_entry_t *libdhcpv6_address_entry_allocate(uint32_t validLifetime) 00223 { 00224 dhcpv6_alloacted_address_entry_t *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_alloacted_address_entry_t)); 00225 if (entry) { 00226 if (validLifetime != 0xffffffff) { 00227 entry->lifetime = validLifetime; 00228 entry->preferredLifetime = (validLifetime >> 1); 00229 } else { 00230 entry->lifetime = 0xffffffff; 00231 entry->preferredLifetime = 0xffffffff; 00232 } 00233 } 00234 return entry; 00235 } 00236 00237 dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) 00238 { 00239 ns_list_foreach(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { 00240 if (memcmp(cur->nonTemporalAddress, address, 16) == 0) { 00241 return cur; 00242 } 00243 } 00244 return NULL; 00245 } 00246 00247 void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) 00248 { 00249 ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { 00250 if (memcmp(cur->nonTemporalAddress, address, 16) == 0) { 00251 ns_list_remove(&serverInfo->allocatedAddressList, cur); 00252 ns_dyn_mem_free(cur); 00253 return; 00254 } 00255 } 00256 } 00257 00258 dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) 00259 { 00260 dhcpv6_alloacted_address_entry_t *newEntry = NULL; 00261 uint16_t duiLength = 6; 00262 if (linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || 00263 linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { 00264 duiLength = 8; 00265 } 00266 ns_list_foreach(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { 00267 if (cur->linkType == linkType) { 00268 if (memcmp(cur->linkId, linkId, duiLength) == 0) { 00269 cur->iaID = iaID; 00270 if (serverInfo->validLifetime != 0xffffffff) { 00271 cur->lifetime = serverInfo->validLifetime ; 00272 cur->preferredLifetime = (serverInfo->validLifetime >> 1); 00273 } else { 00274 cur->lifetime = 0xffffffff; 00275 cur->preferredLifetime = 0xffffffff; 00276 } 00277 return cur; 00278 } 00279 } 00280 } 00281 if (allocateNew) { 00282 if (ns_list_count(&serverInfo->allocatedAddressList) < serverInfo->maxSuppertedClients) { 00283 newEntry = libdhcpv6_address_entry_allocate(serverInfo->validLifetime); 00284 if (newEntry) { 00285 memcpy(newEntry->linkId, linkId, duiLength); 00286 newEntry->linkType = linkType; 00287 newEntry->iaID = iaID; 00288 newEntry->T0 = T0; 00289 newEntry->T1 = T1; 00290 libdhcpv6_address_generate(serverInfo, newEntry); 00291 ns_list_add_to_end(&serverInfo->allocatedAddressList, newEntry); 00292 } 00293 } 00294 } 00295 00296 return newEntry; 00297 } 00298 00299 #endif 00300
Generated on Tue Jul 12 2022 13:54:26 by
