Skip to content

Commit

Permalink
guess the data type of unknown attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
alandekok committed Nov 11, 2024
1 parent f5820f6 commit 4cc6d8c
Showing 1 changed file with 103 additions and 1 deletion.
104 changes: 103 additions & 1 deletion src/lib/util/cbor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1285,6 +1285,104 @@ ssize_t fr_cbor_encode_pair(fr_dbuff_t *dbuff, fr_pair_t *vp)
return fr_dbuff_set(dbuff, &work_dbuff);
}

/** Guess the data type of the CBOR data.
*
* We've parsed the attribute number, and found that we don't have a dictionary entry for it. But rather
* than create an attribute of type octets, we try to guess the data type.
*/
static fr_type_t cbor_guess_type(fr_dbuff_t *dbuff)
{
fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
ssize_t slen;
uint8_t major, info;
uint64_t value;

/*
* get the next byte, which is a CBOR header.
*/
FR_DBUFF_OUT_RETURN(&major, &work_dbuff);

info = major & 0x1f;
major >>= 5;

switch (major) {
case CBOR_INTEGER:
return FR_TYPE_UINT64;

case CBOR_NEGATIVE:
return FR_TYPE_UINT64;

case CBOR_STRING:
return FR_TYPE_STRING;

case CBOR_OCTETS:
return FR_TYPE_OCTETS;

case CBOR_ARRAY:
break; /* this shouldn't happen??? */

case CBOR_MAP:
return FR_TYPE_TLV;

/*
* Look at the tag to determine what it is
*/
case CBOR_TAG:
slen = cbor_decode_integer(&value, info, &work_dbuff);
if (slen < 0) break;

switch (value) {
case 1:
case 1001:
return FR_TYPE_DATE;

case 1002:
return FR_TYPE_TIME_DELTA;

case 48:
return FR_TYPE_ETHERNET;

case 52:
FR_DBUFF_OUT_RETURN(&major, &work_dbuff);

major >>= 5;

if (major == CBOR_ARRAY) {
return FR_TYPE_IPV4_PREFIX;
}
return FR_TYPE_IPV4_ADDR;

case 54:
FR_DBUFF_OUT_RETURN(&major, &work_dbuff);

major >>= 5;

if (major == CBOR_ARRAY) {
return FR_TYPE_IPV6_PREFIX;
}
return FR_TYPE_IPV6_ADDR;

default:
break;
}

break;

case CBOR_FLOAT:
return FR_TYPE_FLOAT64;
}


/*
* No idea. :(
*
* @todo - also check the cbor data, and return the length of cbor data which needs to be
* converted to data type 'octets'. This work involves mostly parsing the cbor data, which isn't
* trivial.
*/
return FR_TYPE_OCTETS;
}

ssize_t fr_cbor_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dbuff_t *dbuff,
fr_dict_attr_t const *parent, bool tainted)
{
Expand Down Expand Up @@ -1327,13 +1425,17 @@ ssize_t fr_cbor_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dbuff_t *db

da = fr_dict_attr_child_by_num(parent, value);
if (!da) {
fr_type_t type;

type = cbor_guess_type(&work_dbuff);

/*
* @todo - the value here isn't a cbor octets type, but is instead cbor data. Since cbor
* is typed, we _could_ perhaps instead discover the type from the cbor data, and then
* use that instead. This would involve creating a function which maps cbor types to our
* data types.
*/
da = fr_dict_attr_unknown_raw_afrom_num(ctx, parent, value);
da = fr_dict_attr_unknown_typed_afrom_num(ctx, parent, value, type);
if (!da) goto oom;
}

Expand Down

0 comments on commit 4cc6d8c

Please sign in to comment.