29#include <freeradius-devel/util/debug.h>
30#include <freeradius-devel/util/base16.h>
31#include <freeradius-devel/util/base64.h>
32#include <freeradius-devel/util/types.h>
33#include <freeradius-devel/util/value.h>
55 .value = { .value_is_always_array =
true },
87#if JSON_C_VERSION_NUM >= 0x1300
88#define json_object_put_assert(_obj) json_object_put(_obj)
90static inline CC_HINT(always_inline)
95 ret = json_object_put(obj);
98 fr_assert_fail(
"json_object_put did not free object (returned %d), likely leaking memory", ret);
119 switch (json_object_get_type(
object)) {
120 case json_type_string:
126 value = json_object_get_string(
object);
127 len = json_object_get_string_len(
object);
129 if (!enumv)
goto no_enumv;
150 case json_type_double:
156#ifdef HAVE_JSON_OBJECT_GET_INT64
162#ifndef HAVE_JSON_OBJECT_GET_INT64
163 num = json_object_get_int(
object);
165 num = json_object_get_int64(
object);
166 if (num < INT32_MIN) {
168 }
else if (num > UINT32_MAX) {
172 if (num < INT16_MIN) {
174 }
else if (num < INT8_MIN) {
176 }
else if (num < 0) {
178 }
else if (num > UINT16_MAX) {
188 case json_type_boolean:
190 fr_value_box(
out, ((
bool)(json_object_get_boolean(
object) > 0)), tainted);
194 case json_type_array:
195 case json_type_object:
197 char const *
value = json_object_to_json_string(
object);
204 out->tainted = tainted;
224 if (enumv)
return json_object_new_string(enumv->
name);
227 switch (
data->type) {
240 return json_object_new_string_len(
data->vb_strvalue,
data->vb_length);
243 return json_object_new_string_len((
char const *)
data->vb_octets,
data->vb_length);
246 return json_object_new_boolean(
data->vb_bool);
249 return json_object_new_int(
data->vb_uint8);
252 return json_object_new_int(
data->vb_uint16);
254#ifdef HAVE_JSON_OBJECT_GET_INT64
256 return json_object_new_int64((int64_t)
data->vb_uint32);
259 if (
data->vb_uint64 > INT64_MAX)
goto do_string;
260 return json_object_new_int64(
data->vb_uint64);
263 if (
data->vb_uint32 > INT32_MAX)
goto do_string;
264 return json_object_new_int(
data->vb_uint32);
268 return json_object_new_int(
data->vb_int8);
271 return json_object_new_int(
data->vb_int16);
274 return json_object_new_int(
data->vb_int32);
276#ifdef HAVE_JSON_OBJECT_GET_INT64
278 return json_object_new_int64(
data->vb_int64);
281 return json_object_new_int64(
data->vb_size);
321 char const *last_app, *p, *end;
325 last_app = p = vb->vb_strvalue;
326 end = p + vb->vb_length;
329 if ((*p <
' ') || (*p ==
'"') || (*p ==
'\\') || (*p ==
'/')) {
421 struct json_object *obj;
424 obj = json_object_new_double((
double)vb->vb_float32);
425 if (
unlikely(obj == NULL))
return -1;
429 if (slen < 0)
return slen;
435 struct json_object *obj;
438 obj = json_object_new_double((
double)vb->vb_float64);
439 if (
unlikely(obj == NULL))
return -1;
443 if (slen < 0)
return slen;
465 if (slen < 0)
return slen;
486#ifdef HAVE_JSON_C_VERSION
487 INFO(
"libfreeradius-json: json-c version: %s", json_c_version());
489 INFO(
"libfreeradius-json: json-c version: Unknown (less than 0.10) - Please upgrade");
507static inline CC_HINT(always_inline)
520 switch (
format->value.binary_format) {
527 switch (
format->value.binary_format) {
555 if (
format->value.always_string) {
596 if (
format->value.enum_as_int) {
622 if (
format->attr.prefix) {
647 switch (
format->output_mode) {
654 if (
format->attr.prefix) {
655 if (verbose)
WARN(
"attribute name prefix not valid in output_mode 'array_of_values' and will be ignored");
658 if (
format->value.value_is_always_array) {
659 if (verbose)
WARN(
"'value_is_always_array' not valid in output_mode 'array_of_values' and will be ignored");
664 if (
format->value.value_is_always_array) {
665 if (verbose)
WARN(
"'value_is_always_array' not valid in output_mode 'array_of_names' and will be ignored");
668 if (
format->value.enum_as_int) {
669 if (verbose)
WARN(
"'enum_as_int' not valid in output_mode 'array_of_names' and will be ignored");
672 if (
format->value.always_string) {
673 if (verbose)
WARN(
"'always_string' not valid in output_mode 'array_of_names' and will be ignored");
678 ERROR(
"JSON format output mode is invalid");
687#define INVALID_TYPE \
690 fr_strerror_printf("Invalid type %s for attribute %s", fr_type_to_str(vp->vp_type), vp->da->name); \
726static CC_HINT(warn_unused_result)
730 struct json_object *obj;
737 MEM(obj = json_object_new_object());
743 struct json_object *vp_object, *values, *
value, *type_name;
745 if (
vp->vp_raw)
continue;
757 switch (
vp->vp_type) {
803 if (!json_object_object_get_ex(obj,
fr_sbuff_start(&attr_name), &vp_object)) {
807 MEM(vp_object = json_object_new_object());
808 json_object_object_add(obj,
fr_sbuff_start(&attr_name), vp_object);
814 json_object_object_add_ex(vp_object,
"type", type_name, JSON_C_OBJECT_KEY_IS_CONSTANT);
819 if (
format->value.value_is_always_array) {
820 MEM(values = json_object_new_array());
821 json_object_object_add_ex(vp_object,
"value", values, JSON_C_OBJECT_KEY_IS_CONSTANT);
822 json_object_array_add(values,
value);
829 json_object_object_add_ex(vp_object,
"value",
value, JSON_C_OBJECT_KEY_IS_CONSTANT);
837 if (!
fr_cond_assert(json_object_object_get_ex(vp_object,
"value", &values))) {
846 if (!
format->value.value_is_always_array) {
848 struct json_object *convert_value = values;
851 type = json_object_get_type(values);
854 if (
type != json_type_array) {
855 MEM(values = json_object_new_array());
856 json_object_array_add(values, json_object_get(convert_value));
857 json_object_object_del(vp_object,
"value");
858 json_object_object_add_ex(vp_object,
"value", values,
859 JSON_C_OBJECT_KEY_IS_CONSTANT);
862 json_object_array_add(values,
value);
897 struct json_object *obj;
905 MEM(obj = json_object_new_object());
911 struct json_object *vp_object, *
value;
912 struct json_object *values = NULL;
913 bool add_single =
false;
915 if (
vp->vp_raw)
continue;
927 switch (
vp->vp_type) {
963 if (!json_object_object_get_ex(obj,
fr_sbuff_start(&attr_name), &vp_object)) {
964 if (
format->value.value_is_always_array) {
969 MEM(values = json_object_new_array());
981 type = json_object_get_type(vp_object);
983 if (
type == json_type_array) {
990 MEM(values = json_object_new_array());
991 json_object_array_add(values, json_object_get(vp_object));
1011 json_object_array_add(values,
value);
1037 struct json_object *obj;
1038 struct json_object *seen_attributes = NULL;
1045 MEM(obj = json_object_new_array());
1051 if (
format->value.value_is_always_array) {
1052 seen_attributes = json_object_new_object();
1059 struct json_object *
name, *
value, *type_name;
1060 struct json_object *values = NULL;
1061 struct json_object *attrobj = NULL;
1062 bool already_seen =
false;
1064 if (
vp->vp_raw)
continue;
1077 switch (
vp->vp_type) {
1094 if (
format->value.value_is_always_array) {
1099 already_seen = json_object_object_get_ex(seen_attributes,
fr_sbuff_start(&attr_name), &values);
1107 if (!
format->value.value_is_always_array || !already_seen) {
1111 MEM(attrobj = json_object_new_object());
1112 json_object_array_add(obj, attrobj);
1118 json_object_object_add_ex(attrobj,
"name",
name, JSON_C_OBJECT_KEY_IS_CONSTANT);
1121 json_object_object_add_ex(attrobj,
"type", type_name, JSON_C_OBJECT_KEY_IS_CONSTANT);
1124 if (
format->value.value_is_always_array) {
1129 if (!already_seen) {
1130 MEM(values = json_object_new_array());
1134 json_object_object_add_ex(attrobj,
"value", values, JSON_C_OBJECT_KEY_IS_CONSTANT);
1139 json_object_object_add(seen_attributes,
fr_sbuff_start(&attr_name), json_object_get(values));
1145 json_object_array_add(values,
value);
1150 json_object_object_add_ex(attrobj,
"value",
value, JSON_C_OBJECT_KEY_IS_CONSTANT);
1158 if (
format->value.value_is_always_array) {
1185 struct json_object *obj;
1191 MEM(obj = json_object_new_array());
1200 struct json_object *
value;
1202 if (
vp->vp_raw)
continue;
1204 switch (
vp->vp_type) {
1216 if (
value == NULL)
goto error;
1223 json_object_array_add(obj,
value);
1249 struct json_object *obj;
1256 MEM(obj = json_object_new_array());
1264 struct json_object *
value;
1267 if (
vp->vp_raw)
continue;
1277 switch (
vp->vp_type) {
1282 json_object_array_add(obj,
value);
1284 if (
value == NULL)
goto error;
1291 json_object_array_add(obj,
value);
1333 struct json_object *obj = NULL;
1339 switch (
format->output_mode) {
1364 MEM(p = json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN));
static int const char char buffer[256]
#define fr_base16_encode(_out, _in)
#define fr_base64_encode(_out, _in, _add_padding)
#define L(_str)
Helper for initialising arrays of string literals.
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Defines a CONF_PAIR to C data type mapping.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
fr_value_box_t const * value
Enum value (what name maps to).
fr_dict_enum_value_t const * fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the structure representing an enum value in a fr_dict_attr_t.
ssize_t fr_dict_valid_name(char const *name, ssize_t len)
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
char const * name
Enum name.
#define FR_DICT_ATTR_MAX_NAME_LEN
Maximum length of a attribute name.
Value of an enumerated attribute.
@ JSON_MODE_ARRAY_OF_NAMES
@ JSON_MODE_OBJECT_SIMPLE
@ JSON_MODE_ARRAY_OF_VALUES
fr_json_format_attr_t attr
Formatting options for attribute names.
@ JSON_BINARY_FORMAT_BASE64
Base64-encode octets values.
@ JSON_BINARY_FORMAT_RAW
Current behaviour - raw bytes as JSON string.
@ JSON_BINARY_FORMAT_BASE16
Base16-encode octets values.
char const * prefix
Prefix to add to all attribute names.
fr_table_num_sorted_t const fr_json_binary_format_table[]
static fr_json_format_t const default_json_format
static void json_object_put_assert(json_object *obj)
char * fr_json_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps, fr_json_format_t const *format)
Returns a JSON string of a list of value pairs.
size_t fr_json_format_table_len
static struct json_object * json_value_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps, fr_json_format_t const *format)
Returns a JSON array of a list of value pairs.
static conf_parser_t const json_format_value_config[]
json_object * json_object_from_value_box(fr_value_box_t const *data)
Convert boxed value_box to a JSON object.
static conf_parser_t const json_format_attr_config[]
size_t fr_json_binary_format_table_len
fr_slen_t fr_json_str_from_value(fr_sbuff_t *out, fr_value_box_t const *vb, bool include_quotes)
Print a value box as its equivalent JSON format without going via a struct json_object (in most cases...
conf_parser_t const fr_json_format_config[]
static int json_afrom_pair(TALLOC_CTX *ctx, json_object **out, fr_pair_t *vp, fr_json_format_t const *format)
Convert fr_pair_t into a JSON object.
static int json_afrom_value_box(TALLOC_CTX *ctx, json_object **out, fr_value_box_t const *vb, fr_json_format_t const *format)
Convert a value box into a JSON object.
void fr_json_version_print(void)
Print JSON-C version.
fr_table_num_sorted_t const fr_json_format_table[]
static struct json_object * json_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps, fr_json_format_t const *format)
Returns a JSON array representation of a list of value pairs.
static json_object * json_object_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps, fr_json_format_t const *format)
Returns a JSON object representation of a list of value pairs.
static struct json_object * json_attr_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps, fr_json_format_t const *format)
Returns a JSON array of a list of value pairs.
int fr_json_object_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, json_object *object, fr_dict_attr_t const *enumv, bool tainted)
Convert json object to fr_value_box_t.
bool fr_json_format_verify(fr_json_format_t const *format, bool verbose)
Verify that the options in fr_json_format_t are valid.
static ssize_t attr_name_with_prefix(fr_sbuff_t *out, fr_dict_attr_t const *da, fr_json_format_t const *format)
Get attribute name with optional prefix.
static json_object * json_simple_obj_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps, fr_json_format_t const *format)
Returns a JSON object representation of a list of value pairs.
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_FLOAT64
Double precision floating point.
int fr_pair_value_enum_box(fr_value_box_t const **out, fr_pair_t *vp)
Get value box of a VP, optionally prefer enum value.
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define FR_SBUFF(_sbuff_or_marker)
#define FR_SBUFF_IN_BSTRNCPY_RETURN(...)
#define fr_sbuff_init_in(_out, _start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
fr_aka_sim_id_type_t type
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
An element in a lexicographically sorted array of name to num mappings.
#define talloc_strdup(_ctx, _str)
Master include file to access all functions and structures in the library.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Support functions to allow libraries to provide errors to their callers.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
@ FR_TYPE_ATTR
A contains an attribute reference.
#define FR_TYPE_STRUCTURAL
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
#define FR_VALUE_BOX_INITIALISER_NULL(_vb)
A static initialiser for stack/globally allocated boxes.
#define fr_value_box(_box, _var, _tainted)
Automagically fill in a box, determining the value type from the type of the C variable.
int format(printf, 5, 0))
static size_t char ** out