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 },
82static inline CC_HINT(always_inline)
87 ret = json_object_put(obj);
90 fr_assert_fail(
"json_object_put did not free object (returned %d), likely leaking memory", ret);
110 switch (json_object_get_type(
object)) {
111 case json_type_string:
117 value = json_object_get_string(
object);
118 len = json_object_get_string_len(
object);
120 if (!enumv)
goto no_enumv;
141 case json_type_double:
147#ifdef HAVE_JSON_OBJECT_GET_INT64
153#ifndef HAVE_JSON_OBJECT_GET_INT64
154 num = json_object_get_int(
object);
156 num = json_object_get_int64(
object);
157 if (num < INT32_MIN) {
159 }
else if (num > UINT32_MAX) {
163 if (num < INT16_MIN) {
165 }
else if (num < INT8_MIN) {
167 }
else if (num < 0) {
169 }
else if (num > UINT16_MAX) {
179 case json_type_boolean:
181 fr_value_box(
out, ((
bool)(json_object_get_boolean(
object) > 0)), tainted);
185 case json_type_array:
186 case json_type_object:
188 char const *
value = json_object_to_json_string(
object);
195 out->tainted = tainted;
215 if (enumv)
return json_object_new_string(enumv->
name);
218 switch (
data->type) {
231 return json_object_new_string_len(
data->vb_strvalue,
data->vb_length);
234 return json_object_new_string_len((
char const *)
data->vb_octets,
data->vb_length);
237 return json_object_new_boolean(
data->vb_bool);
240 return json_object_new_int(
data->vb_uint8);
243 return json_object_new_int(
data->vb_uint16);
245#ifdef HAVE_JSON_OBJECT_GET_INT64
247 return json_object_new_int64((int64_t)
data->vb_uint32);
250 if (
data->vb_uint64 > INT64_MAX)
goto do_string;
251 return json_object_new_int64(
data->vb_uint64);
254 if (
data->vb_uint32 > INT32_MAX)
goto do_string;
255 return json_object_new_int(
data->vb_uint32);
259 return json_object_new_int(
data->vb_int8);
262 return json_object_new_int(
data->vb_int16);
265 return json_object_new_int(
data->vb_int32);
267#ifdef HAVE_JSON_OBJECT_GET_INT64
269 return json_object_new_int64(
data->vb_int64);
272 return json_object_new_int64(
data->vb_size);
312 char const *last_app, *p, *end;
316 last_app = p = vb->vb_strvalue;
317 end = p + vb->vb_length;
320 if ((*p <
' ') || (*p ==
'"') || (*p ==
'\\') || (*p ==
'/')) {
412 struct json_object *obj;
415 obj = json_object_new_double((
double)vb->vb_float32);
416 if (
unlikely(obj == NULL))
return -1;
420 if (slen < 0)
return slen;
426 struct json_object *obj;
429 obj = json_object_new_double((
double)vb->vb_float64);
430 if (
unlikely(obj == NULL))
return -1;
434 if (slen < 0)
return slen;
456 if (slen < 0)
return slen;
477#ifdef HAVE_JSON_C_VERSION
478 INFO(
"libfreeradius-json: json-c version: %s", json_c_version());
480 INFO(
"libfreeradius-json: json-c version: Unknown (less than 0.10) - Please upgrade");
498static inline CC_HINT(always_inline)
511 switch (
format->value.binary_format) {
518 switch (
format->value.binary_format) {
546 if (
format->value.always_string) {
587 if (
format->value.enum_as_int) {
613 if (
format->attr.prefix) {
638 switch (
format->output_mode) {
645 if (
format->attr.prefix) {
646 if (verbose)
WARN(
"attribute name prefix not valid in output_mode 'array_of_values' and will be ignored");
649 if (
format->value.value_is_always_array) {
650 if (verbose)
WARN(
"'value_is_always_array' not valid in output_mode 'array_of_values' and will be ignored");
655 if (
format->value.value_is_always_array) {
656 if (verbose)
WARN(
"'value_is_always_array' not valid in output_mode 'array_of_names' and will be ignored");
659 if (
format->value.enum_as_int) {
660 if (verbose)
WARN(
"'enum_as_int' not valid in output_mode 'array_of_names' and will be ignored");
663 if (
format->value.always_string) {
664 if (verbose)
WARN(
"'always_string' not valid in output_mode 'array_of_names' and will be ignored");
669 ERROR(
"JSON format output mode is invalid");
678#define INVALID_TYPE \
681 fr_strerror_printf("Invalid type %s for attribute %s", fr_type_to_str(vp->vp_type), vp->da->name); \
717static CC_HINT(warn_unused_result)
721 struct json_object *obj;
728 MEM(obj = json_object_new_object());
734 struct json_object *vp_object, *values, *
value, *type_name;
736 if (
vp->vp_raw)
continue;
748 switch (
vp->vp_type) {
794 if (!json_object_object_get_ex(obj,
fr_sbuff_start(&attr_name), &vp_object)) {
798 MEM(vp_object = json_object_new_object());
799 json_object_object_add(obj,
fr_sbuff_start(&attr_name), vp_object);
805 json_object_object_add_ex(vp_object,
"type", type_name, JSON_C_OBJECT_KEY_IS_CONSTANT);
810 if (
format->value.value_is_always_array) {
811 MEM(values = json_object_new_array());
812 json_object_object_add_ex(vp_object,
"value", values, JSON_C_OBJECT_KEY_IS_CONSTANT);
813 json_object_array_add(values,
value);
820 json_object_object_add_ex(vp_object,
"value",
value, JSON_C_OBJECT_KEY_IS_CONSTANT);
828 if (!
fr_cond_assert(json_object_object_get_ex(vp_object,
"value", &values))) {
837 if (!
format->value.value_is_always_array) {
839 struct json_object *convert_value = values;
842 type = json_object_get_type(values);
845 if (
type != json_type_array) {
846 MEM(values = json_object_new_array());
847 json_object_array_add(values, json_object_get(convert_value));
848 json_object_object_del(vp_object,
"value");
849 json_object_object_add_ex(vp_object,
"value", values,
850 JSON_C_OBJECT_KEY_IS_CONSTANT);
853 json_object_array_add(values,
value);
888 struct json_object *obj;
896 MEM(obj = json_object_new_object());
902 struct json_object *vp_object, *
value;
903 struct json_object *values = NULL;
904 bool add_single =
false;
906 if (
vp->vp_raw)
continue;
918 switch (
vp->vp_type) {
954 if (!json_object_object_get_ex(obj,
fr_sbuff_start(&attr_name), &vp_object)) {
955 if (
format->value.value_is_always_array) {
960 MEM(values = json_object_new_array());
972 type = json_object_get_type(vp_object);
974 if (
type == json_type_array) {
981 MEM(values = json_object_new_array());
982 json_object_array_add(values, json_object_get(vp_object));
1002 json_object_array_add(values,
value);
1028 struct json_object *obj;
1029 struct json_object *seen_attributes = NULL;
1036 MEM(obj = json_object_new_array());
1042 if (
format->value.value_is_always_array) {
1043 seen_attributes = json_object_new_object();
1050 struct json_object *
name, *
value, *type_name;
1051 struct json_object *values = NULL;
1052 struct json_object *attrobj = NULL;
1053 bool already_seen =
false;
1055 if (
vp->vp_raw)
continue;
1068 switch (
vp->vp_type) {
1085 if (
format->value.value_is_always_array) {
1090 already_seen = json_object_object_get_ex(seen_attributes,
fr_sbuff_start(&attr_name), &values);
1098 if (!
format->value.value_is_always_array || !already_seen) {
1102 MEM(attrobj = json_object_new_object());
1103 json_object_array_add(obj, attrobj);
1109 json_object_object_add_ex(attrobj,
"name",
name, JSON_C_OBJECT_KEY_IS_CONSTANT);
1112 json_object_object_add_ex(attrobj,
"type", type_name, JSON_C_OBJECT_KEY_IS_CONSTANT);
1115 if (
format->value.value_is_always_array) {
1120 if (!already_seen) {
1121 MEM(values = json_object_new_array());
1125 json_object_object_add_ex(attrobj,
"value", values, JSON_C_OBJECT_KEY_IS_CONSTANT);
1130 json_object_object_add(seen_attributes,
fr_sbuff_start(&attr_name), json_object_get(values));
1136 json_object_array_add(values,
value);
1141 json_object_object_add_ex(attrobj,
"value",
value, JSON_C_OBJECT_KEY_IS_CONSTANT);
1149 if (
format->value.value_is_always_array) {
1176 struct json_object *obj;
1182 MEM(obj = json_object_new_array());
1191 struct json_object *
value;
1193 if (
vp->vp_raw)
continue;
1195 switch (
vp->vp_type) {
1207 if (
value == NULL)
goto error;
1214 json_object_array_add(obj,
value);
1240 struct json_object *obj;
1247 MEM(obj = json_object_new_array());
1255 struct json_object *
value;
1258 if (
vp->vp_raw)
continue;
1268 switch (
vp->vp_type) {
1273 json_object_array_add(obj,
value);
1275 if (
value == NULL)
goto error;
1282 json_object_array_add(obj,
value);
1324 struct json_object *obj = NULL;
1330 switch (
format->output_mode) {
1355 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