Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers libDHCPv6_server.c Source File

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