From: Nick Porter Date: Thu, 12 May 2022 15:52:39 +0000 (+0100) Subject: Define macros for adding a pair to a list and assinging its value (#4507) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de06eb903069612b31a1a0f4e49f0e7c22320a1c;p=thirdparty%2Ffreeradius-server.git Define macros for adding a pair to a list and assinging its value (#4507) --- diff --git a/src/lib/util/pair.h b/src/lib/util/pair.h index 7339a8d0cc1..e6972cf8c49 100644 --- a/src/lib/util/pair.h +++ b/src/lib/util/pair.h @@ -191,6 +191,166 @@ DIAG_ON(nonnull-compare) # define PAIR_LIST_VERIFY(_x) fr_pair_list_nonnull_assert(_x) #endif +/* + * Helper macros for adding pairs to lists and assigning a value to them + */ + +/** Check a pair's data type matches the DA data type + * + * @param[in] vp to check consistency of. + * @return + * - true for match + * - false for error + */ +static inline bool vp_da_data_type_check(fr_pair_t *vp) +{ + if (vp->data.type == vp->da->type) return true; + + fr_strerror_printf("fr_pair_t attribute %p \"%s\" data type (%s) does not match da type (%s)", + vp->da, vp->da->name, + fr_table_str_by_value(fr_type_table, vp->data.type, "invalid"), + fr_table_str_by_value(fr_type_table, vp->da->type, "invalid")); + return false; +} + +/** Append a pair to a list, assigning its value. + * + * Version for simple C data types + * + * @param[in] _ctx to allocate the pair in + * @param[out] _vp the allocated pair + * @param[in] _list to append the pair to + * @param[in] _attr to use when creating pair + * @param[in] _val to assign to the pair + * @param[in] _tainted does the value come from a trusted source + */ +#define fr_pair_list_append_by_da(_ctx, _vp, _list, _attr, _val, _tainted) \ +do { \ + _vp = NULL; \ + if (fr_pair_append_by_da(_ctx, &_vp, _list, _attr) < 0) break; \ + fr_value_box(&_vp->data, _val, _tainted); \ + if (!vp_da_data_type_check(_vp)) { \ + fr_pair_delete(_list, _vp); \ + _vp = NULL; \ + } \ +} while (0) + +/** Append a pair to a list, assigning its value. + * + * Version for char* and uint8_t* + * + * @param[in] _ctx to allocate the pair in + * @param[out] _vp the allocated pair + * @param[in] _list to append the pair to + * @param[in] _attr to use when creating pair + * @param[in] _val to assign to the pair + * @param[in] _len of value + * @param[in] _tainted does the value come from a trusted source + */ +#define fr_pair_list_append_by_da_len(_ctx, _vp, _list, _attr, _val, _len, _tainted) \ +do { \ + _vp = NULL; \ + if (fr_pair_append_by_da(_ctx, &_vp, _list, _attr) < 0) break; \ + fr_value_box_len(_ctx, &_vp->data, _val, _len, _tainted); \ + if (!vp_da_data_type_check(_vp)) { \ + fr_pair_delete(_list, _vp); \ + _vp = NULL; \ + } \ +} while (0) + +/** Prepend a pair to a list, assigning its value + * + * Version for simple C data types + * + * @param[in] _ctx to allocate the pair in + * @param[out] _vp the allocated pair + * @param[in] _list to prepend the pair to + * @param[in] _attr to use when creating pair + * @param[in] _val to assign to the pair + * @param[in] _tainted does the value come from a trusted source + */ +#define fr_pair_list_prepend_by_da(_ctx, _vp, _list, _attr, _val, _tainted) \ +do { \ + _vp = NULL; \ + if (fr_pair_prepend_by_da(_ctx, &_vp, _list, _attr) < 0) break; \ + fr_value_box(&_vp->data, _val, _tainted); \ + if (!vp_da_data_type_check(_vp)) { \ + fr_pair_delete(_list, _vp); \ + _vp = NULL; \ + } \ +} while (0) + +/** Prepend a pair to a list, assigning its value. + * + * Version for char* and uint8_t* + * + * @param[in] _ctx to allocate the pair in + * @param[out] _vp the allocated pair + * @param[in] _list to prepend the pair to + * @param[in] _attr to use when creating pair + * @param[in] _val to assign to the pair + * @param[in] _len of value + * @param[in] _tainted does the value come from a trusted source + */ +#define fr_pair_list_prepend_by_da_len(_ctx, _vp, _list, _attr, _val, _len, _tainted) \ +do { \ + _vp = NULL; \ + if (fr_pair_prepend_by_da(_ctx, &_vp, _list, _attr) < 0) break; \ + fr_value_box_len(_ctx, &_vp->data, _val, _len, _tainted); \ + if (!vp_da_data_type_check(_vp)) { \ + fr_pair_delete(_list, _vp); \ + _vp = NULL; \ + } \ +} while (0) + +/** Replace a pair in a list, assigning its value + * + * Version for simple C data types. + * If the pair does not already exist, a new one is allocated. + * + * @param[in] _ctx to allocate the pair in + * @param[out] _vp the allocated pair + * @param[in] _list to append the pair to + * @param[in] _attr to use when creating pair + * @param[in] _val to assign to the pair + * @param[in] _tainted does the value come from a trusted source + */ +#define fr_pair_list_replace_by_da(_ctx, _vp, _list, _attr, _val, _tainted) \ +do { \ + fr_pair_update_by_da(_ctx, _vp, _list, _attr, 0); \ + if (!vp) break; \ + fr_value_box(&_vp->data, _val, _tainted); \ + if (!vp_da_data_type_check(_vp)) { \ + fr_pair_delete(_list, _vp); \ + _vp = NULL; \ + } \ +} while (0) + +/** Replace a pair in a list, assigning its value + * + * Version for char* and uint8_t* + * If the pair does not already exist, a new one is allocated. + * + * @param[in] _ctx to allocate the pair in + * @param[out] _vp the allocated pair + * @param[in] _list to append the pair to + * @param[in] _attr to use when creating pair + * @param[in] _val to assign to the pair + * @param[in] _len of value + * @param[in] _tainted does the value come from a trusted source + */ +#define fr_pair_list_replace_by_da_len(_ctx, _vp, _list, _attr, _val, _len, _tainted) \ +do { \ + fr_pair_t *oldvp = fr_pair_find_by_da(_list, NULL, _attr); \ + fr_pair_list_append_by_da_len(_ctx, _vp_, _list, _attr, _val, _len, _tainted) \ + if (!vp_da_data_type_check(_vp)) { \ + fr_pair_delete(_list, _vp); \ + _vp = NULL; \ + } \ + if (!_vp) break; \ + if (oldvp) fr_pair_delete(_list, oldvp); \ +} while (0) + /* Initialisation */ void fr_pair_list_init(fr_pair_list_t *head) CC_HINT(nonnull);