Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DHCPv6_Server_service.c Source File

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