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.
libDHCPv6.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 libDHCPv6.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 "ns_trace.h" 00027 #include "common_functions.h" 00028 #include "libDHCPv6/libDHCPv6.h" 00029 #include "randLIB.h" 00030 #include "nsdynmemLIB.h" 00031 #ifdef HAVE_DHCPV6 00032 #define TRACE_GROUP "dhcp" 00033 00034 00035 static NS_LARGE NS_LIST_DEFINE(dhcpv6_client_nonTemporal_list, dhcpv6_client_server_data_t, link); 00036 00037 //Allocate 00038 static dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_entry_allocate(void) 00039 { 00040 dhcpv6_client_server_data_t *newEntry = ns_dyn_mem_alloc(sizeof(dhcpv6_client_server_data_t)); 00041 if (newEntry) { 00042 newEntry->T0 = 0; 00043 newEntry->T1 = 0; 00044 newEntry->reNewTimer = 0; 00045 newEntry->iaNonTemporalStructValid = false; 00046 newEntry->GlobalAddress = false; 00047 newEntry->useServerAddress = false; 00048 newEntry->iaNontemporalAddress.preferredTime = 0; 00049 newEntry->iaNontemporalAddress.validLifetime = 0; 00050 } 00051 return newEntry; 00052 } 00053 00054 static uint32_t libdhcpv6_IAID_generate(void) 00055 { 00056 uint32_t iaId; 00057 bool notUnique = true; 00058 while (notUnique) { 00059 notUnique = false; 00060 iaId = randLIB_get_32bit(); 00061 if (libdhcpv6_nonTemporal_entry_get_by_iaid(iaId)) { 00062 notUnique = true; 00063 } 00064 00065 } 00066 return iaId; 00067 } 00068 00069 static uint32_t libdhcpv6_Tx_timer_generate(uint32_t lifetime, bool T1_get) 00070 { 00071 uint32_t timeout = lifetime; 00072 00073 if (T1_get) { 00074 timeout = (timeout >> 1); 00075 } else { 00076 timeout = (timeout >> 2); 00077 timeout = (timeout * 3); 00078 } 00079 00080 return timeout; 00081 } 00082 00083 uint32_t libdhcpv6_txid_get(void) 00084 { 00085 uint32_t transaction_id = randLIB_get_32bit(); 00086 transaction_id &= 0x00ffffff; 00087 return transaction_id; 00088 } 00089 00090 uint32_t libdhcpv6_renew_time_define(dhcpv6_client_server_data_t *addresInfo) 00091 { 00092 uint32_t renewTimer = 0xffffffff; 00093 00094 if (addresInfo->iaNontemporalAddress.preferredTime < renewTimer) { 00095 renewTimer = addresInfo->iaNontemporalAddress.preferredTime; 00096 } 00097 00098 if (renewTimer == 0xffffffff) { 00099 //Check T1 00100 renewTimer = 0; 00101 } else if (renewTimer < 100) { 00102 renewTimer = 100; 00103 } 00104 00105 if (addresInfo->T0 == 0) { 00106 //Calculate 00107 if (renewTimer != 0) { 00108 addresInfo->T0 = libdhcpv6_Tx_timer_generate(renewTimer, true); 00109 addresInfo->T1 = libdhcpv6_Tx_timer_generate(renewTimer, false); 00110 } else { 00111 addresInfo->T0 = 0xffffffff; 00112 addresInfo->T1 = 0xffffffff; 00113 } 00114 } 00115 00116 //Calculate Renew Time 00117 if (addresInfo->T0 != 0xffffffff) { 00118 renewTimer = addresInfo->T0; 00119 } else { 00120 renewTimer = 0; 00121 } 00122 00123 return renewTimer; 00124 } 00125 00126 dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *duiId, uint16_t duiLinkType, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address) 00127 { 00128 uint32_t iaId; 00129 dhcpv6_client_server_data_t *new_entry = NULL; 00130 if (duiId) { 00131 //allocate new Entry 00132 iaId = libdhcpv6_IAID_generate(); 00133 new_entry = libdhcvp6_nontemporalAddress_entry_allocate(); 00134 if (new_entry) { 00135 new_entry->IAID = iaId; 00136 new_entry->interfaceId = interfaceId; 00137 new_entry->instanceId = instanceId; 00138 //save Cliet ID 00139 memcpy(new_entry->clientId, duiId, 8); 00140 new_entry->clientLinkIdType = duiLinkType; 00141 if (serverIPv6Address) { 00142 memcpy(new_entry->server_address, serverIPv6Address, 16); 00143 new_entry->useServerAddress = true; 00144 } 00145 if (nonTemporalPrefix) { 00146 uint8_t *ptr = new_entry->iaNontemporalAddress.addressPrefix; 00147 memcpy(ptr, nonTemporalPrefix, 8); 00148 memset((ptr + 8), 0, 8); 00149 new_entry->iaNonTemporalStructValid = true; 00150 new_entry->iaNontemporalAddress.preferredTime = 0; 00151 new_entry->iaNontemporalAddress.validLifetime = 0; 00152 } 00153 ns_list_add_to_end(&dhcpv6_client_nonTemporal_list, new_entry); 00154 } 00155 } 00156 return new_entry; 00157 } 00158 00159 void libdhcvp6_nontemporalAddress_server_data_free(dhcpv6_client_server_data_t *removedEntry) 00160 { 00161 if (removedEntry) { 00162 ns_list_remove(&dhcpv6_client_nonTemporal_list, removedEntry); 00163 ns_dyn_mem_free(removedEntry); 00164 } 00165 } 00166 00167 dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_instance(uint8_t instanceId) 00168 { 00169 ns_list_foreach(dhcpv6_client_server_data_t, cur, &dhcpv6_client_nonTemporal_list) { 00170 if (cur->instanceId == instanceId) { 00171 return cur; 00172 } 00173 } 00174 return NULL; 00175 } 00176 uint8_t libdhcpv6_nonTemporal_entry_get_unique_instance_id(void) 00177 { 00178 uint8_t unique_id = 1; 00179 ns_list_foreach(dhcpv6_client_server_data_t, cur, &dhcpv6_client_nonTemporal_list) { 00180 if (cur->instanceId == unique_id) { 00181 unique_id++; 00182 cur = ns_list_get_first(&dhcpv6_client_nonTemporal_list); 00183 } 00184 } 00185 return unique_id; 00186 } 00187 00188 dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_iaid(uint32_t iaId) 00189 { 00190 ns_list_foreach(dhcpv6_client_server_data_t, cur, &dhcpv6_client_nonTemporal_list) { 00191 if (cur->IAID == iaId) { 00192 return cur; 00193 } 00194 } 00195 return NULL; 00196 } 00197 00198 dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_transactionId(uint32_t txId) 00199 { 00200 ns_list_foreach(dhcpv6_client_server_data_t, cur, &dhcpv6_client_nonTemporal_list) { 00201 if (cur->transActionId == txId) { 00202 return cur; 00203 } 00204 } 00205 return NULL; 00206 } 00207 00208 dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_prefix(int8_t interfaceId, uint8_t *prefix) 00209 { 00210 ns_list_foreach(dhcpv6_client_server_data_t, cur, &dhcpv6_client_nonTemporal_list) { 00211 if ((cur->interfaceId == interfaceId) && cur->iaNonTemporalStructValid) { 00212 if (memcmp(cur->iaNontemporalAddress.addressPrefix, prefix , 8) == 0) { 00213 return cur; 00214 } 00215 } 00216 } 00217 return NULL; 00218 } 00219 00220 uint16_t libdhcpv6_duid_option_size(uint16_t linkType) 00221 { 00222 uint16_t length = 8; // Type & Length header part *2 00223 if (linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) { 00224 length += 8; 00225 } else { 00226 length += 6; 00227 } 00228 00229 return length; 00230 } 00231 00232 uint16_t libdhcpv6_client_data_option_size(uint16_t linkType) 00233 { 00234 uint16_t optionLength = 4; 00235 optionLength += libdhcpv6_duid_option_size(linkType); 00236 optionLength += libdhcpv6_ia_address_option_size(); 00237 optionLength += libdhcpv6_client_last_transaction_time_option_size(); 00238 return optionLength; 00239 } 00240 00241 uint16_t libdhcvp6_request_option_size(uint8_t optionCnt) 00242 { 00243 uint16_t optionLength = 4; 00244 optionLength += 2 * optionCnt; 00245 return optionLength; 00246 } 00247 00248 uint16_t libdhcpv6_non_temporal_address_size(bool addressDefined) 00249 { 00250 uint16_t optionLength = 16; 00251 if (addressDefined) { 00252 optionLength += libdhcpv6_ia_address_option_size(); 00253 } 00254 return optionLength; 00255 } 00256 00257 int libdhcpv6_message_malformed_check(uint8_t *ptr, uint16_t data_len) 00258 { 00259 uint8_t *dptr; 00260 uint16_t length; 00261 if (data_len > 4) { 00262 dptr = ptr + 4; //Skip Type & TXID 00263 data_len -= 4; 00264 while (data_len) { 00265 if (data_len >= 4) { 00266 00267 length = common_read_16_bit(dptr + 2); //Skip Type 00268 dptr += 4; 00269 data_len -= 4; 00270 if (data_len >= length) { 00271 data_len -= length; 00272 dptr += length; 00273 } 00274 } else { 00275 return -1; 00276 } 00277 } 00278 } 00279 return 0; 00280 } 00281 00282 00283 /** 00284 * This Function write dhcpv6 basic header 00285 * 00286 * \param ptr pointer where header will be writed 00287 * \param msgType dhcpv6 message type 00288 * \param transActionId 24-bit unique Trasnaction ID 00289 * 00290 * return incremented pointer after write 00291 */ 00292 uint8_t *libdhcpv6_header_write(uint8_t *ptr, uint8_t msgType, uint32_t transActionId) 00293 { 00294 *ptr++ = msgType; 00295 ptr = common_write_24_bit(transActionId, ptr); 00296 return ptr; 00297 } 00298 00299 uint8_t *libdhcpv6_elapsed_time_option_write(uint8_t *ptr, uint16_t elapsedTime) 00300 { 00301 //Elapsed time 00302 ptr = common_write_16_bit(DHCPV6_ELAPSED_TIME_OPTION, ptr); 00303 ptr = common_write_16_bit(DHCPV6_ELAPSED_TIME_OPTION_LEN, ptr); 00304 ptr = common_write_16_bit(elapsedTime, ptr); 00305 return ptr; 00306 } 00307 00308 uint8_t *libdhcpv6_rapid_commit_option_write(uint8_t *ptr) 00309 { 00310 ptr = common_write_16_bit(DHCPV6_OPTION_RAPID_COMMIT, ptr); 00311 ptr = common_write_16_bit(DHCPV6_OPTION_RAPID_COMMIT_LEN, ptr); 00312 return ptr; 00313 } 00314 00315 uint8_t *libdhcvp6_vendor_specific_option_write(uint8_t *ptr, uint8_t *data, uint16_t dataLength) 00316 { 00317 ptr = common_write_16_bit(DHCPV6_OPTION_VENDOR_SPECIFIC_INFO, ptr); 00318 ptr = common_write_16_bit(dataLength, ptr); 00319 memcpy(ptr, data, dataLength); 00320 ptr += dataLength; 00321 return ptr; 00322 } 00323 00324 uint8_t *libdhcvp6_request_option_write(uint8_t *ptr, uint8_t optionCnt, uint16_t *optionPtr) 00325 { 00326 uint16_t optionLength = libdhcvp6_request_option_size(optionCnt); 00327 ptr = common_write_16_bit(DHCPV6_OPTION_REQUEST_OPTION, ptr); 00328 ptr = common_write_16_bit((optionLength - 4), ptr); 00329 while (optionCnt) { 00330 ptr = common_write_16_bit(*optionPtr++, ptr); 00331 optionCnt--; 00332 } 00333 return ptr; 00334 } 00335 00336 uint8_t *libdhcpv6_duid_option_write(uint8_t *ptr, uint16_t duidRole, const dhcp_link_options_params_t *duid) 00337 { 00338 uint16_t length = libdhcpv6_duid_option_size(duid->linkType); 00339 00340 length -= 4; //Cut normal option header out 00341 ptr = common_write_16_bit(duidRole, ptr); 00342 ptr = common_write_16_bit(length, ptr); 00343 ptr = common_write_16_bit(DHCPV6_DUID_LINK_LAYER_TYPE, ptr); 00344 ptr = common_write_16_bit(duid->linkType, ptr); 00345 length -= 4; //Cut normal option header out 00346 memcpy(ptr, duid->linkID, length); 00347 ptr += length; 00348 return ptr; 00349 } 00350 00351 uint8_t *libdhcpv6_prefix_delegation_info_option_write(uint8_t *ptr, uint32_t iaId) 00352 { 00353 ptr = common_write_16_bit(DHCPV6_OPTION_IA_PREFIX_DELEGATION, ptr); 00354 ptr = common_write_16_bit(DHCPV6_OPTION_IA_PREFIX_DELEGATION_MIN_LENGTH, ptr); 00355 ptr = common_write_32_bit(iaId, ptr); 00356 ptr = common_write_32_bit(0, ptr); //T1 00357 ptr = common_write_32_bit(0, ptr);//T2 00358 return ptr; 00359 } 00360 00361 uint8_t *libdhcpv6_identity_association_option_write(uint8_t *ptr, uint32_t iaID, uint32_t TimerT1, uint32_t TimerT2, bool withAddress) 00362 { 00363 uint16_t optionMsgLen = libdhcpv6_non_temporal_address_size(withAddress); 00364 00365 ptr = common_write_16_bit(DHCPV6_IDENTITY_ASSOCIATION_OPTION, ptr); 00366 ptr = common_write_16_bit((optionMsgLen - 4), ptr); 00367 00368 ptr = common_write_32_bit(iaID, ptr); //iaId 00369 ptr = common_write_32_bit(TimerT1, ptr); //T1 00370 ptr = common_write_32_bit(TimerT2, ptr);//T2 00371 return ptr; 00372 } 00373 00374 uint8_t *libdhcpv6_identity_association_option_write_with_status(uint8_t *ptr, uint32_t iaID, uint32_t TimerT1, uint32_t TimerT2, uint16_t status) 00375 { 00376 uint16_t optionMsgLen = libdhcpv6_non_temporal_address_size(false); 00377 00378 optionMsgLen += 6; // add status option length 00379 00380 ptr = common_write_16_bit(DHCPV6_IDENTITY_ASSOCIATION_OPTION, ptr); 00381 ptr = common_write_16_bit((optionMsgLen - 4), ptr); 00382 00383 ptr = common_write_32_bit(iaID, ptr); //iaId 00384 ptr = common_write_32_bit(TimerT1, ptr); //T1 00385 ptr = common_write_32_bit(TimerT2, ptr);//T2 00386 ptr = libdhcpv6_status_code_write(ptr, status); 00387 return ptr; 00388 } 00389 00390 uint8_t *libdhcpv6_ia_address_option_write(uint8_t *ptr, const uint8_t *addressPtr, uint32_t preferredValidLifeTime, uint32_t validLifeTime) 00391 { 00392 ptr = common_write_16_bit(DHCPV6_IA_ADDRESS_OPTION, ptr); 00393 ptr = common_write_16_bit(DHCPV6_IA_ADDRESS_OPTION_LEN, ptr); 00394 memcpy(ptr, addressPtr, 16); 00395 ptr += 16; 00396 ptr = common_write_32_bit(preferredValidLifeTime, ptr); //Preferred 00397 ptr = common_write_32_bit(validLifeTime, ptr);//Valid 00398 return ptr; 00399 } 00400 00401 uint8_t *libdhcpv6_status_code_write(uint8_t *ptr, uint16_t statusCode) 00402 { 00403 ptr = common_write_16_bit(DHCPV6_STATUS_CODE_OPTION, ptr); 00404 ptr = common_write_16_bit(DHCPV6_STATUS_CODE_OPTION_LEN, ptr); 00405 ptr = common_write_16_bit(statusCode, ptr); 00406 return ptr; 00407 } 00408 00409 uint8_t *libdhcpv6_client_last_transaction_time_option_write(uint8_t *ptr, uint32_t last_transaction_Time) 00410 { 00411 00412 uint16_t Length = libdhcpv6_client_last_transaction_time_option_size(); 00413 ptr = common_write_16_bit(DHCPV6_OPTION_CLT_TIME, ptr); 00414 ptr = common_write_16_bit((Length - 4), ptr); 00415 ptr = common_write_32_bit(last_transaction_Time, ptr); //SET Last time we heard from this child either from mle or data packets. 00416 return ptr; 00417 } 00418 00419 int libdhcpv6_message_option_discover(uint8_t *ptr, uint16_t data_len, uint16_t discovered_type, dhcp_options_msg_t *option_info) 00420 { 00421 uint8_t *dptr; 00422 uint16_t type, length; 00423 dptr = ptr; 00424 if( data_len < 4 ){ 00425 tr_warn("libdhcpv6_message_option_discover() data_len<4"); 00426 return -1; 00427 } 00428 while (data_len >= 4) { 00429 type = common_read_16_bit(dptr); 00430 dptr += 2; 00431 length = common_read_16_bit(dptr); 00432 dptr += 2; 00433 data_len -= 4; 00434 if (data_len >= length) { 00435 if (type == discovered_type) { 00436 option_info->len = length; 00437 option_info->type = type; 00438 option_info->msg_ptr = dptr; 00439 return 0; 00440 } 00441 data_len -= length; 00442 dptr += length; 00443 } else { 00444 tr_warn("libdhcpv6_message_option_discover() data_len<length=%"PRIu16, length); 00445 break; 00446 } 00447 } 00448 return -1; 00449 } 00450 00451 int libdhcpv6_compare_DUID(dhcp_link_options_params_t *targetId, dhcp_link_options_params_t *parsedId) 00452 { 00453 if (targetId->linkType == parsedId->linkType) { 00454 uint8_t cmpLen; 00455 if (targetId->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) { 00456 //Compare Current Interface EUID64 00457 cmpLen = 8; 00458 } else { 00459 cmpLen = 6; 00460 } 00461 if (memcmp(targetId->linkID, parsedId->linkID, cmpLen) == 0) { 00462 return 0; 00463 } 00464 } 00465 return -1; 00466 } 00467 00468 int libdhcpv6_reply_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length) 00469 { 00470 /** 00471 * Solication Message Should Include Next Options: 00472 * - DHCPV6_SERVER_ID_OPTION 00473 * - DHCPV6_CLIENT_ID_OPTION 00474 * - DHCPV6_IDENTITY_ASSOCIATION_OPTION 00475 * 00476 */ 00477 /** Verify Client ID */ 00478 if (libdhcpv6_get_duid_by_selected_type_id_opt(ptr, data_length, DHCPV6_CLIENT_ID_OPTION , clientId) != 0) { 00479 return -1; 00480 } 00481 00482 if (libdhcpv6_get_duid_by_selected_type_id_opt(ptr, data_length, DHCPV6_SERVER_ID_OPTION, serverId) != 0) { 00483 return -1; 00484 } 00485 00486 if (libdhcpv6_get_IA_address(ptr, data_length, dhcp_ia_non_temporal_params) != 0) { 00487 return -1; 00488 } 00489 00490 return 0; 00491 } 00492 00493 int libdhcpv6_advertisment_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length) 00494 { 00495 /** 00496 * Solication Message Should Include Next Options: 00497 * - DHCPV6_SERVER_ID_OPTION 00498 * - DHCPV6_CLIENT_ID_OPTION 00499 * - DHCPV6_IDENTITY_ASSOCIATION_OPTION 00500 * 00501 */ 00502 /** Verify Client ID to own EUID64 */ 00503 if (libdhcpv6_get_duid_by_selected_type_id_opt(ptr, data_length, DHCPV6_CLIENT_ID_OPTION , clientId) != 0) { 00504 return -1; 00505 } 00506 00507 if (libdhcpv6_get_duid_by_selected_type_id_opt(ptr, data_length, DHCPV6_SERVER_ID_OPTION, serverId) != 0) { 00508 return -1; 00509 } 00510 00511 if (libdhcpv6_get_IA_address(ptr, data_length, dhcp_ia_non_temporal_params) != 0) { 00512 return -1; 00513 } 00514 00515 return 0; 00516 } 00517 #ifdef HAVE_DHCPV6_SERVER 00518 int libdhcpv6_renew_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_link_options_params_t *clientLinkData, dhcp_link_options_params_t *serverLinkData, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params) 00519 { 00520 00521 /** 00522 * Renew Message Should Include Next Options: 00523 * - DHCPV6_ELAPSED_TIME_OPTION 00524 * - DHCPV6_CLIENT_ID_OPTION 00525 * - DHCPV6_SERVER_ID_OPTION 00526 * - DHCPV6_IDENTITY_ASSOCIATION_OPTION 00527 * - DHCPV6_OPTION_REQUEST_OPTION 00528 * Optionally: 00529 * - DHCPV6_OPTION_REQUEST_RAPID_COMMIT 00530 */ 00531 00532 /** Verify First DHCPV6_ELAPSED_TIME_OPTION */ 00533 if (libdhcpv6_time_elapsed_option_at_packet(ptr, data_length) == false) { 00534 return -1; 00535 } 00536 /** Verify DHCPV6_CLIENT_ID_OPTION */ 00537 if (libdhcpv6_get_duid_by_selected_type_id_opt(ptr, data_length, DHCPV6_CLIENT_ID_OPTION, clientLinkData) != 0) { 00538 return -1; 00539 } 00540 /** Verify DHCPV6_SERVER_ID_OPTION */ 00541 if (libdhcpv6_get_duid_by_selected_type_id_opt(ptr, data_length, DHCPV6_SERVER_ID_OPTION, serverLinkData) != 0) { 00542 return -1; 00543 } 00544 00545 /** Verify DHCPV6_IDENTITY_ASSOCIATION_OPTION */ 00546 if (libdhcpv6_get_IA_address(ptr, data_length, dhcp_ia_non_temporal_params) != 0) { 00547 return -1; 00548 } 00549 00550 return 0; 00551 } 00552 00553 00554 00555 int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_link_options_params_t *clientLink, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params) 00556 { 00557 /** 00558 * Solication Message Should Include Next Options: 00559 * - DHCPV6_ELAPSED_TIME_OPTION 00560 * - DHCPV6_CLIENT_ID_OPTION 00561 * - DHCPV6_IDENTITY_ASSOCIATION_OPTION 00562 * - DHCPV6_OPTION_REQUEST_OPTION 00563 * Optionally: 00564 * - DHCPV6_OPTION_REQUEST_RAPID_COMMIT 00565 */ 00566 /** Verify First DHCPV6_ELAPSED_TIME_OPTION */ 00567 00568 if (libdhcpv6_time_elapsed_option_at_packet(ptr, data_length) == false) { 00569 return -1; 00570 } 00571 /** Verify DHCPV6_CLIENT_ID_OPTION */ 00572 if (libdhcpv6_get_duid_by_selected_type_id_opt(ptr, data_length, DHCPV6_CLIENT_ID_OPTION, clientLink) != 0) { 00573 return -1; 00574 } 00575 00576 00577 /** Verify DHCPV6_IDENTITY_ASSOCIATION_OPTION */ 00578 if (libdhcpv6_get_IA_address(ptr, data_length, dhcp_ia_non_temporal_params) != 0) { 00579 return -1; 00580 } 00581 00582 return 0; 00583 } 00584 #endif 00585 00586 bool libdhcpv6_time_elapsed_option_at_packet(uint8_t *ptr, uint16_t length) 00587 { 00588 bool retVal = false; 00589 dhcp_options_msg_t option_msg; 00590 /** Verify First DHCPV6_ELAPSED_TIME_OPTION */ 00591 00592 if (libdhcpv6_message_option_discover(ptr, length, DHCPV6_ELAPSED_TIME_OPTION, &option_msg) == 0) { 00593 if (option_msg.len == DHCPV6_ELAPSED_TIME_OPTION_LEN) { 00594 retVal = true; 00595 } 00596 } 00597 return retVal; 00598 } 00599 00600 bool libdhcpv6_rapid_commit_option_at_packet(uint8_t *ptr, uint16_t length) 00601 { 00602 bool retVal = false; 00603 dhcp_options_msg_t option_msg; 00604 if (libdhcpv6_message_option_discover(ptr, length, DHCPV6_OPTION_RAPID_COMMIT, &option_msg) == 0) { 00605 retVal = true; 00606 } 00607 return retVal; 00608 } 00609 00610 int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type , dhcp_link_options_params_t *params) 00611 { 00612 dhcp_options_msg_t option_msg; 00613 00614 /** Verify DHCPV6_CLIENT_ID_OPTION */ 00615 if (libdhcpv6_message_option_discover(ptr, data_length, type, &option_msg) == 0) { 00616 if (option_msg.len >= DHCPV6_SERVER_ID_MAC48_OPTION_LEN) { 00617 uint8_t *t_ptr = option_msg.msg_ptr; 00618 type = common_read_16_bit(t_ptr); 00619 t_ptr += 2; 00620 params->linkType = common_read_16_bit(t_ptr); 00621 t_ptr += 2; 00622 if (type == DHCPV6_DUID_LINK_LAYER_TYPE) { 00623 params->linkID = t_ptr; 00624 if ((params->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) && (option_msg.len == DHCPV6_SERVER_ID_MAC48_OPTION_LEN)) { 00625 return 0; 00626 } else if ((params->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) && (option_msg.len == DHCPV6_SERVER_ID_MAC64_OPTION_LEN)) { 00627 return 0; 00628 } 00629 } 00630 } 00631 } 00632 00633 return -1; 00634 } 00635 00636 int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_temporal_params_t *params) 00637 { 00638 dhcp_options_msg_t option_msg; 00639 uint16_t status_code = 0; 00640 00641 if (libdhcpv6_message_option_discover(ptr, data_length, DHCPV6_STATUS_CODE_OPTION, &option_msg) == 0) { 00642 if (option_msg.len >= DHCPV6_STATUS_CODE_OPTION_LEN) { 00643 status_code = common_read_16_bit(option_msg.msg_ptr); 00644 if (status_code == DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE) { 00645 return -1; 00646 } 00647 } 00648 } 00649 00650 if (libdhcpv6_message_option_discover(ptr, data_length, DHCPV6_IDENTITY_ASSOCIATION_OPTION, &option_msg) == 0) { 00651 if (option_msg.len < DHCPV6_IDENTITY_ASSOCIATION_OPTION_MIN_LEN) { 00652 return -1; 00653 } 00654 uint8_t *t_ptr; 00655 uint16_t length; 00656 t_ptr = option_msg.msg_ptr; 00657 length = (option_msg.len - 12); 00658 params->iaId = common_read_32_bit(t_ptr); 00659 t_ptr += 4; 00660 params->T0 = common_read_32_bit(t_ptr); 00661 t_ptr += 4; 00662 params->T1 = common_read_32_bit(t_ptr); 00663 t_ptr += 4; 00664 00665 if(length > 4) { 00666 if (libdhcpv6_message_option_discover(t_ptr, length, DHCPV6_STATUS_CODE_OPTION, &option_msg) == 0) { 00667 if (option_msg.len >= DHCPV6_STATUS_CODE_OPTION_LEN) { 00668 status_code = common_read_16_bit(option_msg.msg_ptr); 00669 if (status_code != 0) { 00670 return -1; 00671 } 00672 } 00673 } 00674 00675 if (libdhcpv6_message_option_discover(t_ptr, length, DHCPV6_IA_ADDRESS_OPTION, &option_msg) == 0) { 00676 if (option_msg.len >= DHCPV6_IA_ADDRESS_OPTION_LEN) { 00677 t_ptr = option_msg.msg_ptr; 00678 params->nonTemporalAddress = t_ptr; 00679 t_ptr += 16; 00680 params->preferredValidLifeTime = common_read_32_bit(t_ptr); 00681 t_ptr += 4; 00682 params->validLifeTime = common_read_32_bit(t_ptr); 00683 return 0; 00684 } 00685 } 00686 } 00687 } 00688 return -1; 00689 } 00690 00691 uint16_t libdhcpv6_address_request_message_len(uint16_t clientLinkType, uint16_t serverLinkType, uint8_t requstOptionCnt) 00692 { 00693 uint16_t length = 0; 00694 length += libdhcpv6_header_size(); 00695 length += libdhcpv6_elapsed_time_option_size(); 00696 length += libdhcpv6_duid_option_size(clientLinkType); 00697 length += libdhcpv6_duid_option_size(serverLinkType); 00698 length += libdhcvp6_request_option_size(requstOptionCnt); 00699 length += libdhcpv6_rapid_commit_option_size(); 00700 length += libdhcpv6_non_temporal_address_size(true); 00701 return length; 00702 } 00703 #ifdef HAVE_DHCPV6_SERVER 00704 uint16_t libdhcpv6_address_reply_message_len(uint16_t clientLinkType, uint16_t serverLinkType, uint16_t vendorDataLen, bool rapidCommon, bool status) 00705 { 00706 uint16_t length = 0; 00707 00708 length += libdhcpv6_header_size(); 00709 length += libdhcpv6_duid_option_size(clientLinkType); 00710 length += libdhcpv6_duid_option_size(serverLinkType); 00711 if (rapidCommon) { 00712 length += libdhcpv6_rapid_commit_option_size(); 00713 } 00714 00715 if (vendorDataLen) { 00716 length += (vendorDataLen + 4); 00717 } 00718 00719 if (status) { 00720 length += libdhcpv6_non_temporal_address_size(true); 00721 } else { 00722 length += libdhcpv6_non_temporal_address_size(false); 00723 length += libdhcpv6_status_option_size(); 00724 } 00725 00726 return length; 00727 } 00728 #endif 00729 00730 uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_link_options_params_t *serverLink) 00731 { 00732 bool add_address = false; 00733 if (nonTemporalAddress) { 00734 add_address = true; 00735 } 00736 //Start Build Packet 00737 ptr = libdhcpv6_header_write(ptr, packet->messageType, packet->transActionId); 00738 //Elapsed time 00739 ptr = libdhcpv6_elapsed_time_option_write(ptr, 0); 00740 //Client Identifier 00741 ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_CLIENT_ID_OPTION, &packet->clientDUID); //16 00742 //SET Server ID if It is defined 00743 if (serverLink) { 00744 ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_SERVER_ID_OPTION, serverLink); 00745 } 00746 00747 //SET Server ID 00748 ptr = libdhcpv6_rapid_commit_option_write(ptr); 00749 //Request Option 00750 ptr = libdhcvp6_request_option_write(ptr, packet->requestedOptionCnt, packet->requestedOptionList); 00751 //CLient Identity Association 00752 00753 ptr = libdhcpv6_identity_association_option_write(ptr, packet->iaID, packet->timerT0, packet->timerT1, add_address); 00754 if (add_address) { 00755 ptr = libdhcpv6_ia_address_option_write(ptr, nonTemporalAddress->requestedAddress, nonTemporalAddress->preferredLifeTime, nonTemporalAddress->validLifeTime); 00756 } 00757 00758 return ptr; 00759 } 00760 00761 00762 uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *replyPacket, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcpv6_vendor_data_packet_s *vendorData) 00763 { 00764 ptr = libdhcpv6_header_write(ptr, DHCPV6_REPLY_TYPE, replyPacket->transaction_ID); 00765 ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_SERVER_ID_OPTION, &replyPacket->serverDUID); //16 00766 ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_CLIENT_ID_OPTION, &replyPacket->clientDUID); //16 00767 00768 if (nonTemporalAddress) { 00769 ptr = libdhcpv6_identity_association_option_write(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, true); 00770 ptr = libdhcpv6_ia_address_option_write(ptr, nonTemporalAddress->requestedAddress, nonTemporalAddress->preferredLifeTime, nonTemporalAddress->validLifeTime); 00771 } else { 00772 ptr = libdhcpv6_identity_association_option_write_with_status(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE); 00773 } 00774 00775 if (vendorData) { 00776 ptr = libdhcvp6_vendor_specific_option_write(ptr, vendorData->vendorData, vendorData->vendorDataLength); 00777 } 00778 00779 if (replyPacket->rapidCommit) { 00780 ptr = libdhcpv6_rapid_commit_option_write(ptr); 00781 } 00782 00783 return ptr; 00784 } 00785 00786 uint16_t libdhcpv6_solication_message_length(uint16_t clientLinkType, bool addressDefined, uint8_t requestOptionCount) 00787 { 00788 uint16_t length = 0; 00789 length += libdhcpv6_header_size(); 00790 length += libdhcpv6_elapsed_time_option_size(); 00791 length += libdhcpv6_rapid_commit_option_size(); 00792 length += libdhcpv6_duid_option_size(clientLinkType); 00793 length += libdhcpv6_non_temporal_address_size(addressDefined); 00794 length += libdhcvp6_request_option_size(requestOptionCount); 00795 return length; 00796 } 00797 00798 #endif
Generated on Tue Jul 12 2022 14:23:51 by
