Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers libDHCPv6_server.c Source File

libDHCPv6_server.c

00001 /*
00002  * Copyright (c) 2014-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 /*
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     if (entry) {
00045         entry->clientIdSequence = 0;
00046         entry->enableAddressMapping = false;
00047         entry->enableAddressAutonous = true;
00048         entry->clientIdDefaultSuffics = 0x0000000;
00049         entry->maxSuppertedClients = 200;
00050         entry->validLifetime = 7200;
00051         ns_list_init(&entry->allocatedAddressList);
00052     }
00053     return entry;
00054 }
00055 static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_alloacted_address_entry_t *entry)
00056 {
00057     //GENERATE ADDRESS
00058     uint8_t *ptr = entry->nonTemporalAddress;
00059     memcpy(ptr, serverInfo->guaPrefix, 8);
00060     ptr += 8;
00061     if (serverInfo->enableAddressAutonous) {
00062         if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) {
00063             memcpy(ptr, entry->linkId, 8);
00064             *ptr ^= 2;
00065         } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) {
00066             *ptr++  = entry->linkId[0] ^ 2;
00067             *ptr++  = entry->linkId[1];
00068             *ptr++  = entry->linkId[2];
00069             *ptr++  = 0xff;
00070             *ptr++  = 0xfe;
00071             *ptr++  = entry->linkId[3];
00072             *ptr++  = entry->linkId[4];
00073             *ptr    = entry->linkId[5];
00074         } else {
00075             ptr = common_write_32_bit((serverInfo->clientIdDefaultSuffics | 02000000), ptr);
00076             ptr = common_write_32_bit((serverInfo->clientIdSequence + 2), ptr);
00077         }
00078 
00079     } else {
00080         ptr = common_write_32_bit((serverInfo->clientIdDefaultSuffics | 02000000), ptr);
00081         ptr = common_write_32_bit((serverInfo->clientIdSequence + 2), ptr);
00082     }
00083     serverInfo->clientIdSequence++;
00084 }
00085 
00086 
00087 void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds)
00088 {
00089     //Check All allocated server inside this loop
00090     ns_list_foreach(dhcpv6_gua_server_entry_s, cur, &dhcpv6_gua_server_list) {
00091         //Check All allocated address in this module
00092         ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, address, &cur->allocatedAddressList) {
00093             //Update
00094             if (address->preferredLifetime) {
00095                 if (address->preferredLifetime <= timeUpdateInSeconds) {
00096                     //Stop use this address for leasequery and delete Route or address map
00097 
00098                     address->preferredLifetime = 0;
00099                     cur->timeoutCb(cur->interfaceId, address->nonTemporalAddress);
00100                 } else {
00101                     address->preferredLifetime -= timeUpdateInSeconds;
00102                 }
00103             }
00104 
00105             if (address->lifetime <= timeUpdateInSeconds) {
00106                 ns_list_remove(&cur->allocatedAddressList, address);
00107                 ns_dyn_mem_free(address);
00108             } else {
00109                 address->lifetime -= timeUpdateInSeconds;
00110             }
00111         }
00112     }
00113 }
00114 
00115 dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_interfaceid(int8_t interfaceId, const uint8_t *prefixPtr)
00116 {
00117     ns_list_foreach(dhcpv6_gua_server_entry_s, cur, &dhcpv6_gua_server_list) {
00118         if (cur->interfaceId == interfaceId) {
00119             if (memcmp(cur->guaPrefix, prefixPtr, 8) == 0) {
00120                 return cur;
00121             }
00122         }
00123     }
00124     return NULL;
00125 }
00126 
00127 dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstance(uint16_t socketInstance, uint8_t *prefixPtr)
00128 {
00129     ns_list_foreach(dhcpv6_gua_server_entry_s, cur, &dhcpv6_gua_server_list) {
00130         if (cur->socketInstance_id == socketInstance) {
00131             if (memcmp(cur->guaPrefix, prefixPtr, 8) == 0) {
00132                 return cur;
00133             }
00134         }
00135     }
00136     return NULL;
00137 }
00138 
00139 
00140 dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType, dhcp_address_prefer_timeout_cb *prefered_timeout_cb)
00141 {
00142     dhcpv6_gua_server_entry_s *entry = NULL;
00143     if (libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix) == NULL) {
00144         entry = libdhcpv6_server_entry_allocate();
00145         if (entry) {
00146             memcpy(entry->guaPrefix, prefix, 8);
00147             memcpy(entry->serverDUID, serverDUID, 8);
00148             entry->serverLinkType = serverDUIDType;
00149             entry->interfaceId = interfaceId;
00150             entry->timeoutCb = prefered_timeout_cb;
00151             ns_list_add_to_end(&dhcpv6_gua_server_list, entry);
00152         }
00153     }
00154     return entry;
00155 }
00156 
00157 void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId)
00158 {
00159     dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix);
00160     if (serverInfo) {
00161         if ((serverInfo->interfaceId == interfaceId) && (memcmp(serverInfo->guaPrefix, prefix, 8) == 0)) {
00162             ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) {
00163                 ns_list_remove(&serverInfo->allocatedAddressList, cur);
00164                 ns_dyn_mem_free(cur);
00165             }
00166             ns_list_remove(&dhcpv6_gua_server_list, serverInfo);
00167             ns_dyn_mem_free(serverInfo);
00168         }
00169     }
00170 }
00171 
00172 static dhcpv6_alloacted_address_entry_t *libdhcpv6_address_entry_allocate(uint32_t validLifetime)
00173 {
00174     dhcpv6_alloacted_address_entry_t *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_alloacted_address_entry_t));
00175     if (entry) {
00176         if (validLifetime != 0xffffffff) {
00177             entry->lifetime = validLifetime;
00178             entry->preferredLifetime = (validLifetime >> 1);
00179         } else {
00180             entry->lifetime = 0xffffffff;
00181             entry->preferredLifetime = 0xffffffff;
00182         }
00183     }
00184     return entry;
00185 }
00186 
00187 dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address)
00188 {
00189     ns_list_foreach(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) {
00190         if (memcmp(cur->nonTemporalAddress, address, 16) == 0) {
00191             return cur;
00192         }
00193     }
00194     return NULL;
00195 }
00196 
00197 void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address)
00198 {
00199     ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) {
00200         if (memcmp(cur->nonTemporalAddress, address, 16) == 0) {
00201             ns_list_remove(&serverInfo->allocatedAddressList, cur);
00202             ns_dyn_mem_free(cur);
00203             return;
00204         }
00205     }
00206 }
00207 
00208 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)
00209 {
00210     dhcpv6_alloacted_address_entry_t *newEntry = NULL;
00211     uint16_t duiLength = 6;
00212     if (linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) {
00213         duiLength = 8;
00214     }
00215     ns_list_foreach(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) {
00216         if (cur->linkType == linkType) {
00217             if (memcmp(cur->linkId, linkId, duiLength) == 0) {
00218                 cur->iaID = iaID;
00219                 if (serverInfo->validLifetime != 0xffffffff) {
00220                     cur->lifetime = serverInfo->validLifetime ;
00221                     cur->preferredLifetime = (serverInfo->validLifetime  >> 1);
00222                 } else {
00223                     cur->lifetime = 0xffffffff;
00224                     cur->preferredLifetime = 0xffffffff;
00225                 }
00226                 return cur;
00227             }
00228         }
00229     }
00230     if (allocateNew) {
00231         if (ns_list_count(&serverInfo->allocatedAddressList) < serverInfo->maxSuppertedClients) {
00232             newEntry = libdhcpv6_address_entry_allocate(serverInfo->validLifetime);
00233             if (newEntry) {
00234                 memcpy(newEntry->linkId, linkId, duiLength);
00235                 newEntry->linkType = linkType;
00236                 newEntry->iaID = iaID;
00237                 newEntry->T0 = T0;
00238                 newEntry->T1 = T1;
00239                 libdhcpv6_address_generate(serverInfo, newEntry);
00240                 ns_list_add_to_end(&serverInfo->allocatedAddressList, newEntry);
00241             }
00242         }
00243     }
00244 
00245     return newEntry;
00246 }
00247 
00248 #endif
00249