diff --git a/src/cmdu.c b/src/cmdu.c index b2671e9d6625697cee4b4dea51f52d4575f7db4a..d476b234fca533cc20a08100313647a972a7c3af 100644 --- a/src/cmdu.c +++ b/src/cmdu.c @@ -424,6 +424,46 @@ struct tlv *cmdu_reserve_tlv(struct cmdu_buff *c, uint16_t tlv_datalen) return (struct tlv *)c->tail; } +int cmdu_parse_tlv_single(struct cmdu_buff *c, struct tlv *tv[], + struct tlv_policy *policy, int *num) +{ + struct tlv *t; + int i = 0; + int len; + + + if (!c) + return -1; + + if (*num == 0) + return 0; + + memset(tv, 0, *num * sizeof(struct tlv *)); + len = c->datalen; + + cmdu_for_each_tlv(t, c->data, len) { + if (policy->type != t->type) + continue; + + if (policy->minlen > 0 && tlv_length(t) < policy->minlen) + continue; + + if (policy->maxlen > 0 && tlv_length(t) > policy->maxlen) + continue; + + if (tv[0] && policy->present == TLV_PRESENT_ONE) + break; + + if (i >= *num) + break; + + tv[i++] = t; + } + + *num = i; + return 0; +} + int cmdu_parse_tlvs(struct cmdu_buff *c, struct tlv *tv[][16], struct tlv_policy *policy, int policy_len) { diff --git a/src/cmdu.h b/src/cmdu.h index 7152e73ca67556861d17985c859f1f0deb6377cc..34a9e74f9f544da003c3a5299149f326d8606fcf 100644 --- a/src/cmdu.h +++ b/src/cmdu.h @@ -281,6 +281,25 @@ int is_cmdu_tlv_required(uint16_t type); int cmdu_parse_tlvs(struct cmdu_buff *c, struct tlv *tv[][16], struct tlv_policy *policy, int policy_len); + +/** Parse a CMDU to get list of the TLVs of a single type + * + * @param[in] c cmdu_buff for parsing + * @param[in|out] tv array of TLVs to hold the returned TLVs + * @param[in] policy policy for TLV parsing + * @param[in|out] *num number of TLVs + * + * @return 0 on success, else non-zero. + * + * This function can be used when number of TLVs of the same type is present + * more then 16 times; f.e. CMDUs containing TLVs for scanresults. + * The TLVs are returned in the passed 'tv' array. And, *num is updated with + * the actual number of TLVs present. + */ +int cmdu_parse_tlv_single(struct cmdu_buff *c, struct tlv *tv[], + struct tlv_policy *policy, int *num); + + /** Copy append flattended TLVs data buffer into a CMDU */ int cmdu_copy_tlvs_linear(struct cmdu_buff *c, uint8_t *tlvs, uint32_t tlvslen);