BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
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 12:21:58 by
