Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mle_tlv.c Source File

mle_tlv.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 #include "nsconfig.h"
00018 #include "ns_trace.h"
00019 #include "string.h"
00020 #include "MLE/mle.h"
00021 #include "MLE/mle_tlv.h"
00022 #include "common_functions.h"
00023 #include "Service_Libs/mle_service/mle_service_api.h"
00024 
00025 int mle_message_malformed_check(uint8_t *ptr, uint16_t data_len)
00026 {
00027     uint8_t *dptr;
00028     uint16_t length;
00029     dptr = ptr;
00030     while (data_len) {
00031         if (data_len >= 2) {
00032             dptr += 1; //Skip TLV Type
00033             length = *dptr++;
00034             if (length == 0xff) {
00035                 // Long length format
00036                 data_len -= 2;
00037                 if (data_len < 2) {
00038                     return -1;
00039                 }
00040                 length = common_read_16_bit(dptr);
00041                 dptr += 2;
00042             }
00043             data_len -= 2;
00044             if (data_len >= length) {
00045                 if (length) {
00046                     data_len -= length;
00047                     dptr += length;
00048                 }
00049             } else {
00050                 // buffer is overrun this is malformed.
00051                 return -1;
00052             }
00053         } else {
00054             return -1;
00055         }
00056     }
00057     return 0;
00058 }
00059 
00060 int mle_tlv_option_discover(uint8_t *ptr, uint16_t data_len, mle_tlv_type_t discovered_type, mle_tlv_info_t *option_info)
00061 {
00062     uint8_t *dptr;
00063     uint16_t length;
00064     mle_tlv_type_t type;
00065 
00066     option_info->tlvLen = 0;
00067     option_info->tlvType = MLE_TYPE_UNASSIGNED;
00068     option_info->dataPtr = NULL;
00069     dptr = ptr;
00070     while (data_len) {
00071         type = (mle_tlv_type_t) * dptr++;
00072         length = *dptr++;
00073         if (length == 0xff) {
00074             // Long length format
00075             data_len -= 2;
00076             if (data_len < 2) {
00077                 return -1;
00078             }
00079             length = common_read_16_bit(dptr);
00080             dptr += 2;
00081         }
00082         data_len -= 2;
00083         if (data_len >= length) {
00084             if (type == discovered_type) {
00085                 option_info->tlvLen = length;
00086                 option_info->tlvType = type;
00087                 option_info->dataPtr = dptr;
00088                 return length;
00089             } else {
00090                 data_len -= length;
00091                 dptr += length;
00092             }
00093         }
00094     }
00095     return -1;
00096 }
00097 
00098 bool mle_tlv_type_requested(uint8_t reqType, uint8_t *ptr, uint16_t data_len)
00099 {
00100     mle_tlv_info_t tlv_info;
00101     bool retVal = false;
00102     if (mle_tlv_option_discover(ptr, data_len, MLE_TYPE_TLV_REQUEST, &tlv_info) > 0) {
00103         uint16_t i;
00104         uint8_t *t_ptr;
00105         t_ptr = tlv_info.dataPtr;
00106         for (i = 0; i < tlv_info.tlvLen; i++) {
00107             if (*t_ptr++ == reqType) {
00108                 retVal = true;
00109                 break;
00110             }
00111         }
00112     }
00113     return retVal;
00114 }
00115 
00116 bool mle_tlv_read_8_bit_tlv(mle_tlv_type_t reqType, uint8_t *ptr, uint16_t data_len, uint8_t *buffer)
00117 {
00118     mle_tlv_info_t tlv_info;
00119     if (mle_tlv_option_discover(ptr, data_len, reqType, &tlv_info) >= 1) {
00120         uint8_t *t_ptr;
00121         t_ptr = tlv_info.dataPtr;
00122         *buffer = *t_ptr;
00123         return true;
00124     }
00125 
00126     return false;
00127 }
00128 bool mle_tlv_read_16_bit_tlv(mle_tlv_type_t reqType, uint8_t *ptr, uint16_t data_len, uint16_t *buffer)
00129 {
00130     mle_tlv_info_t tlv_info;
00131     if (mle_tlv_option_discover(ptr, data_len, reqType, &tlv_info) >= 2) {
00132         *buffer = common_read_16_bit(tlv_info.dataPtr);
00133         return true;
00134     }
00135 
00136     return false;
00137 }
00138 bool mle_tlv_read_32_bit_tlv(mle_tlv_type_t reqType, uint8_t *ptr, uint16_t data_len, uint32_t *buffer)
00139 {
00140     mle_tlv_info_t tlv_info;
00141     if (mle_tlv_option_discover(ptr, data_len, reqType, &tlv_info) >= 4) {
00142         *buffer = common_read_32_bit(tlv_info.dataPtr);
00143         return true;
00144     }
00145 
00146     return false;
00147 }
00148 
00149 bool mle_tlv_read_64_bit_tlv(mle_tlv_type_t reqType, uint8_t *ptr, uint16_t data_len, uint64_t *buffer)
00150 {
00151     mle_tlv_info_t tlv_info;
00152     if (mle_tlv_option_discover(ptr, data_len, reqType, &tlv_info) >= 8) {
00153         *buffer = common_read_64_bit(tlv_info.dataPtr);
00154         return true;
00155     }
00156 
00157     return false;
00158 }
00159 
00160 bool mle_registerd_address_data_check(uint8_t *ptr, uint8_t length)
00161 {
00162     uint8_t context;
00163     if (length < 9) {
00164         return false;
00165     }
00166 
00167     while (length) {
00168         context = *ptr++;
00169         if (context & 0x80) {
00170             if (length < 9) {
00171                 return false;
00172             }
00173             ptr += 8;
00174             length -= 9;
00175         } else {
00176             if (length < 17) {
00177                 return false;
00178             }
00179             ptr += 16;
00180             length -= 17;
00181         }
00182     }
00183     return true;
00184 }
00185 
00186 bool mle_tlv_read_tlv(mle_tlv_type_t reqType, uint8_t *ptr, uint16_t data_len, mle_tlv_info_t *tlv_info)
00187 {
00188     int length;
00189     length = mle_tlv_option_discover(ptr, data_len, reqType, tlv_info);
00190     if (length != -1) {
00191         if (reqType == MLE_TYPE_CHALLENGE && length > 3) { //32-bit challenge MIN which is accepted
00192             return true;
00193         } else if (reqType == MLE_TYPE_RESPONSE && length > 3) { //32-bit challenge MIN which is accepted
00194             return true;
00195         } else if (reqType == MLE_TYPE_ADDRESS_REGISTRATION && length) {
00196             return mle_registerd_address_data_check(tlv_info->dataPtr, length);
00197         } else if (reqType == MLE_TYPE_ROUTE && length >= 9) {
00198             return true;
00199         } else if (reqType == MLE_TYPE_LINK_METRICS_REPORT) {
00200             return true;
00201         }else if (reqType == MLE_TYPE_TLV_REQUEST || reqType ==  MLE_TYPE_NETWORK_DATA ||
00202                    reqType ==  MLE_TYPE_PENDING_OPERATIONAL_DATASET || reqType ==  MLE_TYPE_OPERATIONAL_DATASET) {
00203             return true;
00204         }
00205     }
00206     return false;
00207 }
00208 
00209 uint8_t *mle_tlv_write_response(uint8_t *ptr, uint8_t *response_ptr, uint8_t responseLen)
00210 {
00211     *ptr++ = MLE_TYPE_RESPONSE;
00212     *ptr++ = responseLen;
00213     memcpy(ptr, response_ptr,  responseLen);
00214     ptr += responseLen;
00215     return ptr;
00216 }
00217 
00218 uint8_t *mle_tlv_write_source_address(uint8_t *ptr, uint16_t shortAddress)
00219 {
00220     *ptr++ = MLE_TYPE_SRC_ADDRESS;
00221     *ptr++ = 2;
00222     ptr = common_write_16_bit(shortAddress, ptr);
00223     return ptr;
00224 }
00225 
00226 uint8_t *mle_tlv_write_short_address(uint8_t *ptr, uint16_t shortAddress)
00227 {
00228     *ptr++ = MLE_TYPE_ADDRESS16;
00229     *ptr++ = 2;
00230     ptr = common_write_16_bit(shortAddress, ptr);
00231     return ptr;
00232 }
00233 
00234 uint8_t *mle_tlv_write_mode(uint8_t *ptr, uint8_t mode)
00235 {
00236     *ptr++ = MLE_TYPE_MODE;
00237     *ptr++ = 1;
00238     *ptr++ = mode;
00239     return ptr;
00240 }
00241 
00242 uint8_t *mle_tlv_write_timeout(uint8_t *ptr, uint32_t timeOut)
00243 {
00244     *ptr++ = MLE_TYPE_TIMEOUT;
00245     *ptr++ = 4;
00246     ptr = common_write_32_bit(timeOut, ptr);
00247     return ptr;
00248 }
00249 
00250 uint8_t *mle_tlv_write_challenge(uint8_t *ptr, uint8_t *challengePtr, uint8_t challenLen)
00251 {
00252     *ptr++ = MLE_TYPE_CHALLENGE;
00253     *ptr++ = challenLen;
00254     memcpy(ptr, challengePtr, challenLen);
00255     ptr += challenLen;
00256     return ptr;
00257 }
00258 
00259 uint8_t *mle_tlv_write_link_layer_framecount(uint8_t *ptr, uint32_t frameCount)
00260 {
00261     *ptr++ = MLE_TYPE_LL_FRAME_COUNTER;
00262     *ptr++ = 4;
00263     ptr = common_write_32_bit(frameCount, ptr);
00264     return ptr;
00265 }
00266 
00267 uint8_t *mle_tlv_write_framecounter(uint8_t *ptr, uint32_t frameCount)
00268 {
00269     *ptr++ = MLE_TYPE_MLE_FRAME_COUNTER;
00270     *ptr++ = 4;
00271     ptr = common_write_32_bit(frameCount, ptr);
00272     return ptr;
00273 }
00274 
00275 uint8_t *mle_tlv_write_scan_mask(uint8_t *ptr, uint8_t scanMask)
00276 {
00277     *ptr++ = MLE_TYPE_SCAN_MASK;
00278     *ptr++ = 1;
00279     *ptr++ = scanMask;
00280     return ptr;
00281 }
00282 uint8_t *mle_tlv_req_tlv(uint8_t *ptr, uint8_t *mle_req_tlv_list, uint8_t req_list_len)
00283 {
00284     *ptr++ = MLE_TYPE_TLV_REQUEST;
00285     *ptr++ = req_list_len;
00286     memcpy(ptr, mle_req_tlv_list, req_list_len);
00287     ptr += req_list_len;
00288     return ptr;
00289 }
00290 uint8_t *mle_tlv_rssi_tlv(uint8_t *ptr, uint8_t linkMargin)
00291 {
00292     *ptr++ = MLE_TYPE_RSSI;
00293     *ptr++ = 1;
00294     *ptr++ = linkMargin;
00295     return ptr;
00296 }
00297 
00298 uint8_t *mle_tlv_write_version(uint8_t *ptr, uint16_t version)
00299 {
00300     *ptr++ = MLE_TYPE_VERSION;
00301     *ptr++ = 2;
00302     ptr = common_write_16_bit(version, ptr);
00303     return ptr;
00304 }
00305 
00306 uint8_t *mle_tlv_write_link_quality(uint8_t *ptr, uint8_t incoming_idr, uint8_t *mac64, uint16_t short_address, uint8_t priority_flag)
00307 {
00308     *ptr++ = MLE_TYPE_LINK_QUALITY;
00309     if (mac64) {
00310         *ptr++ = 11;
00311         *ptr++ = 0x07; /* 8 bytes long address */
00312     } else {
00313         *ptr++ = 5;
00314         *ptr++ = 0x01; /* 2 bytes long address */
00315     }
00316 
00317     if (priority_flag) {
00318         *ptr++ = MLE_NEIGHBOR_PRIORITY_LINK | MLE_NEIGHBOR_INCOMING_LINK | MLE_NEIGHBOR_OUTGOING_LINK;
00319     } else {
00320         *ptr++ = MLE_NEIGHBOR_INCOMING_LINK | MLE_NEIGHBOR_OUTGOING_LINK;
00321     }
00322 
00323     *ptr++ = incoming_idr;
00324 
00325     if (mac64) {
00326         memcpy(ptr, mac64, 8);
00327         ptr += 8;
00328     } else {
00329         ptr = common_write_16_bit(short_address, ptr);
00330     }
00331 
00332     return ptr;
00333 }
00334 
00335 /**
00336  * This function will be used for validate response from ACCEPT or ACCEPT Request message
00337  */
00338 uint16_t mle_tlv_validate_response(uint8_t *ptr, uint16_t data_len)
00339 {
00340     mle_tlv_info_t tlv_info;
00341     uint16_t msgId = 0;
00342     if (mle_tlv_option_discover(ptr, data_len, MLE_TYPE_RESPONSE, &tlv_info) > 3) {
00343         mle_service_transaction_buffer_get_for_response(tlv_info.dataPtr, tlv_info.tlvLen, &msgId);
00344         return msgId;
00345     }
00346     return msgId;
00347 }
00348 
00349 bool mle_tlv_requested(uint8_t *tlv_ptr, uint16_t tlv_len, uint8_t tlv_type)
00350 {
00351     for (uint16_t i=0; i < tlv_len; i++) {
00352         if (tlv_ptr[i] == tlv_type) {
00353             return true;
00354         }
00355     }
00356     return false;
00357 }
00358 
00359 void mle_tlv_ignore(uint8_t *tlv_ptr, uint16_t tlv_len, uint8_t tlv_type)
00360 {
00361     for (uint16_t i=0; i < tlv_len; i++) {
00362         if (tlv_ptr[i] == tlv_type) {
00363             tlv_ptr[i] = MLE_TYPE_UNASSIGNED;
00364         }
00365     }
00366 }
00367