The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
json.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 434a667a0820bbe020760d8c3d160fe832ace3c1 $
19 * @file json.c
20 * @brief Common functions for working with json-c
21 *
22 * @author Arran Cudbard-Bell
23 * @author Matthew Newton
24 *
25 * @copyright 2015 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
26 * @copyright 2015,2020 Network RADIUS SAS (legal@networkradius.com)
27 * @copyright 2015 The FreeRADIUS Server Project
28 */
29#include <freeradius-devel/util/debug.h>
30#include <freeradius-devel/util/base16.h>
31#include <freeradius-devel/util/sbuff.h>
32#include <freeradius-devel/util/types.h>
33#include <freeradius-devel/util/value.h>
34#include "base.h"
35
37 { L("array"), JSON_MODE_ARRAY },
38 { L("array_of_names"), JSON_MODE_ARRAY_OF_NAMES },
39 { L("array_of_values"), JSON_MODE_ARRAY_OF_VALUES },
40 { L("object"), JSON_MODE_OBJECT },
41 { L("object_simple"), JSON_MODE_OBJECT_SIMPLE },
42};
44
46 .attr = { .prefix = NULL },
47 .value = { .value_is_always_array = true },
48 .output_mode = JSON_MODE_OBJECT
49};
50
55
57 { FR_CONF_OFFSET("single_value_as_array", fr_json_format_value_t, value_is_always_array), .dflt = "no" },
58 { FR_CONF_OFFSET("enum_as_integer", fr_json_format_value_t, enum_as_int), .dflt = "no" },
59 { FR_CONF_OFFSET("always_string", fr_json_format_value_t, always_string), .dflt = "no" },
61};
62
64 { FR_CONF_OFFSET("output_mode", fr_json_format_t, output_mode_str), .dflt = "object" },
67
69};
70
71static inline CC_HINT(always_inline)
72void json_object_put_assert(json_object *obj)
73{
74 int ret;
75
76 ret = json_object_put(obj);
77 if (ret == 1) return;
78
79 fr_assert_fail("json_object_put did not free object (returned %u), likely leaking memory", ret);
80}
81
82/** Convert json object to fr_value_box_t
83 *
84 * @param[in] ctx to allocate any value buffers in (should usually be the same as out).
85 * @param[in] out Where to write value. Must be initialised.
86 * @param[in] object to convert.
87 * @param[in] enumv Any string values are assumed to be in PRESENTATION format, meaning
88 * that if an enumv is specified, they'll be checked against the list
89 * of aliases for that enumeration, and possibly converted into one of
90 * the enumeration values (which may not be a string).
91 * @param[in] tainted Whether the data source is untrusted.
92 * @return
93 * - 0 on success.
94 * - -1 on failure.
95 */
96int fr_json_object_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, json_object *object,
97 fr_dict_attr_t const *enumv, bool tainted)
98{
99 switch (json_object_get_type(object)) {
100 case json_type_string:
101 {
102 char const *value;
103 size_t len;
104 fr_dict_enum_value_t const *found;
105
106 value = json_object_get_string(object);
107 len = json_object_get_string_len(object);
108
109 if (!enumv) goto no_enumv;
110
111 if (fr_dict_valid_name(value, len) < 0) goto no_enumv;
112
113 /*
114 * If an alias exists, use that value instead
115 */
116 found = fr_dict_enum_by_name(enumv, value, len);
117 if (found) {
118 if (fr_value_box_copy(ctx, out, found->value) < 0) return -1;
119 return 0;
120 }
121
122 no_enumv:
123 /*
124 * Just copy the string to the box.
125 */
126 fr_value_box_bstrndup(out, out, NULL, value, len, tainted);
127 }
128 break;
129
130 case json_type_double:
131 fr_value_box(out, json_object_get_double(object), tainted);
132 break;
133
134 case json_type_int:
135 {
136#ifdef HAVE_JSON_OBJECT_GET_INT64
137 int64_t num;
138#else
139 int32_t num;
140#endif
141
142#ifndef HAVE_JSON_OBJECT_GET_INT64
143 num = json_object_get_int(object);
144#else
145 num = json_object_get_int64(object);
146 if (num < INT32_MIN) { /* 64bit signed*/
147 fr_value_box(out, (int64_t)num, tainted);
148 } else if (num > UINT32_MAX) { /* 64bit unsigned */
149 fr_value_box(out, (uint64_t)num, tainted);
150 } else
151#endif
152 if (num < INT16_MIN) { /* 32bit signed */
153 fr_value_box(out, (int32_t)num, tainted);
154 } else if (num < INT8_MIN) { /* 16bit signed */
155 fr_value_box(out, (int16_t)num, tainted);
156 } else if (num < 0) { /* 8bit signed */
157 fr_value_box(out, (int8_t)num, tainted);
158 } else if (num > UINT16_MAX) { /* 32bit unsigned */
159 fr_value_box(out, (uint32_t)num, tainted);
160 } else if (num > UINT8_MAX) { /* 16bit unsigned */
161 fr_value_box(out, (uint16_t)num, tainted);
162 } else { /* 8bit unsigned */
163 fr_value_box(out, (uint8_t)num, tainted);
164 }
165 }
166 break;
167
168 case json_type_boolean:
169 /* Must be cast to bool for correct generic case selection */
170 fr_value_box(out, ((bool)(json_object_get_boolean(object) > 0)), tainted);
171 break;
172
173 case json_type_null:
174 case json_type_array:
175 case json_type_object:
176 {
177 char const *value = json_object_to_json_string(object);
178
179 fr_value_box_bstrndup(out, out, NULL, value, strlen(value), tainted);
180 }
181 break;
182 }
183
184 out->tainted = tainted;
185
186 return 0;
187}
188
189/** Convert boxed value_box to a JSON object
190 *
191 * @param[in] data to convert.
192 */
194{
195 /*
196 * We're converting to PRESENTATION format
197 * so any attributes with enumeration values
198 * should be converted to string types.
199 */
200 if (data->enumv) {
201 fr_dict_enum_value_t const *enumv;
202
203 enumv = fr_dict_enum_by_value(data->enumv, data);
204 if (enumv) return json_object_new_string(enumv->name);
205 }
206
207 switch (data->type) {
208 default:
209 do_string:
210 {
211 char buffer[64];
212 fr_sbuff_t sbuff = FR_SBUFF_IN(buffer, sizeof(buffer));
213
214 if (fr_value_box_print(&sbuff, data, NULL) <= 0) return NULL;
215
216 return json_object_new_string_len(buffer, fr_sbuff_used(&sbuff));
217 }
218
219 case FR_TYPE_STRING:
220 return json_object_new_string_len(data->vb_strvalue, data->vb_length);
221
222 case FR_TYPE_OCTETS:
223 return json_object_new_string_len((char const *)data->vb_octets, data->vb_length);
224
225 case FR_TYPE_BOOL:
226 return json_object_new_boolean(data->vb_uint8);
227
228 case FR_TYPE_UINT8:
229 return json_object_new_int(data->vb_uint8);
230
231 case FR_TYPE_UINT16:
232 return json_object_new_int(data->vb_uint16);
233
234#ifdef HAVE_JSON_OBJECT_GET_INT64
235 case FR_TYPE_UINT32:
236 return json_object_new_int64((int64_t)data->vb_uint64); /* uint32_t (max) > int32_t (max) */
237
238 case FR_TYPE_UINT64:
239 if (data->vb_uint64 > INT64_MAX) goto do_string;
240 return json_object_new_int64(data->vb_uint64);
241#else
242 case FR_TYPE_UINT32:
243 if (data->vb_uint32 > INT32_MAX) goto do_string;
244 return json_object_new_int(data->vb_uint32);
245#endif
246
247 case FR_TYPE_INT8:
248 return json_object_new_int(data->vb_int8);
249
250 case FR_TYPE_INT16:
251 return json_object_new_int(data->vb_int16);
252
253 case FR_TYPE_INT32:
254 return json_object_new_int(data->vb_int32);
255
256#ifdef HAVE_JSON_OBJECT_GET_INT64
257 case FR_TYPE_INT64:
258 return json_object_new_int64(data->vb_int64);
259
260 case FR_TYPE_SIZE:
261 return json_object_new_int64(data->vb_size);
262#endif
263
265 return NULL;
266 }
267}
268
269/** Print a value box as its equivalent JSON format without going via a struct json_object (in most cases)
270 *
271 * @param[out] out buffer to write to.
272 * @param[in] vb to print.
273 * @param[in] include_quotes whether we should wrap string values,
274 * or non-native types like IPv4 addresses in quotes.
275 * @return
276 * - <0 on error.
277 * - >= number of bytes written.
278 */
280{
281 fr_sbuff_t our_out = FR_SBUFF(out);
282
283 switch (vb->type) {
284 case FR_TYPE_NULL:
285 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "null");
286 break;
287
288 case FR_TYPE_BOOL:
289 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, vb->vb_bool ? "true" : "false");
290 break;
291
292 /*
293 * This is identical to JSON-C's escaping function
294 * but we avoid creating JSON objects just to be able
295 * to escape strings.
296 */
297 case FR_TYPE_STRING:
298 case FR_TYPE_OCTETS:
299 {
300 char const *last_app, *p, *end;
301
302 if (include_quotes) FR_SBUFF_IN_CHAR_RETURN(&our_out, '"');
303
304 last_app = p = vb->vb_strvalue;
305 end = p + vb->vb_length;
306
307 while (p < end) {
308 if (*p < ' ') {
309 if (p > last_app) FR_SBUFF_IN_BSTRNCPY_RETURN(&our_out, last_app, p - last_app);
310
311 switch (*p) {
312 case '\b':
313 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\b");
314 break;
315
316 case '\n':
317 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\n");
318 break;
319
320 case '\r':
321 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\r");
322 break;
323
324 case '\t':
325 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\t");
326 break;
327
328 case '\f':
329 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\f");
330 break;
331
332 case '"':
333 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\\"");
334 break;
335
336 case '\\':
337 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\\\");
338 break;
339
340 case '/':
341 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\/");
342 break;
343
344 default:
345 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "\\u00");
346 fr_base16_encode(&our_out, &FR_DBUFF_TMP((uint8_t const *)p, 1));
347 }
348
349 last_app = p + 1;
350 }
351 p++;
352 }
353 if (end > last_app) FR_SBUFF_IN_BSTRNCPY_RETURN(&our_out, last_app, end - last_app);
354 if (include_quotes) FR_SBUFF_IN_CHAR_RETURN(&our_out, '"');
355 }
356 break;
357
358 case FR_TYPE_UINT8:
359 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", vb->vb_uint8);
360 break;
361
362 case FR_TYPE_UINT16:
363 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", vb->vb_uint16);
364 break;
365
366 case FR_TYPE_UINT32:
367 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", vb->vb_uint32);
368 break;
369
370 case FR_TYPE_UINT64:
371 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", vb->vb_uint64);
372 break;
373
374 case FR_TYPE_INT8:
375 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%i", vb->vb_int8);
376 break;
377
378 case FR_TYPE_INT16:
379 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%i", vb->vb_int16);
380 break;
381
382 case FR_TYPE_INT32:
383 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%i", vb->vb_int32);
384 break;
385
386 case FR_TYPE_INT64:
387 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%i", vb->vb_int64);
388 break;
389
390 case FR_TYPE_SIZE:
391 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%zu", vb->vb_size);
392 break;
393
394 /*
395 * It's too complex to replicate the float/double printing
396 * here, so pass it off to JSON-C's printing functions.
397 */
398 case FR_TYPE_FLOAT32:
399 {
400 struct json_object *obj;
401 fr_slen_t slen;
402
403 obj = json_object_new_double((double)vb->vb_float32);
404 if (unlikely(obj == NULL)) return -1;
405 slen = fr_sbuff_in_strcpy(&our_out, json_object_to_json_string(obj));
407 return slen;
408 }
409
410 case FR_TYPE_FLOAT64:
411 {
412 struct json_object *obj;
413 fr_slen_t slen;
414
415 obj = json_object_new_double((double)vb->vb_float64);
416 if (unlikely(obj == NULL)) return -1;
417 slen = fr_sbuff_in_strcpy(&our_out, json_object_to_json_string(obj));
419 return slen;
420 }
421
428 case FR_TYPE_IFID:
429 case FR_TYPE_ETHERNET:
430 case FR_TYPE_DATE:
432 case FR_TYPE_ATTR:
433 {
434 fr_slen_t slen;
435
436 if (include_quotes) FR_SBUFF_IN_CHAR_RETURN(&our_out, '"');
437 slen = fr_value_box_print(&our_out, vb, NULL);
438 if (include_quotes) FR_SBUFF_IN_CHAR_RETURN(&our_out, '"');
439 if (slen < 0) return slen;
440 }
441 break;
442
444 fr_strerror_const("Structural boxes not yet supported");
445 return -1;
446
447 case FR_TYPE_INTERNAL:
448 fr_strerror_printf("Box type %s cannot be converted to string", fr_type_to_str(vb->type));
449 return -1;
450 }
451
452 return fr_sbuff_set(out, &our_out);
453}
454
455/** Print JSON-C version
456 *
457 */
459{
460#ifdef HAVE_JSON_C_VERSION
461 INFO("libfreeradius-json: json-c version: %s", json_c_version());
462#else
463 INFO("libfreeradius-json: json-c version: Unknown (less than 0.10) - Please upgrade");
464#endif
465}
466
467
468/** Convert fr_pair_t into a JSON object
469 *
470 * If format.value.enum_as_int is set, and the given VP is an enum
471 * value, the integer value is returned as a json_object rather
472 * than the text representation.
473 *
474 * If format.value.always_string is set then a numeric value pair
475 * will be returned as a JSON string object.
476 *
477 * @param[in] ctx Talloc context.
478 * @param[out] out returned json object.
479 * @param[in] vp to get the value of.
480 * @param[in] format format definition, or NULL.
481 * @return
482 * - 1 if 'out' is the integer enum value, 0 otherwise
483 * - -1 on error.
484 */
485static int json_afrom_value_box(TALLOC_CTX *ctx, json_object **out,
486 fr_pair_t *vp, fr_json_format_t const *format)
487{
488 struct json_object *obj;
489 fr_value_box_t const *vb;
491 int is_enum = 0;
492
493 fr_assert(vp);
494
495 vb = &vp->data;
496
497 if (format && format->value.enum_as_int) {
498 is_enum = fr_pair_value_enum_box(&vb, vp);
499 fr_assert(is_enum >= 0);
500 }
501
502 if (format && format->value.always_string) {
503 if (fr_value_box_cast(ctx, &vb_str, FR_TYPE_STRING, NULL, vb) < 0) {
504 return -1;
505 }
506
507 vb = &vb_str;
508 }
509
511
512 if (format && format->value.always_string) {
513 fr_value_box_clear(&vb_str);
514 }
515
516 *out = obj;
517 return is_enum;
518}
519
520
521/** Get attribute name with optional prefix
522 *
523 * If the format "attr.prefix" string is set then prepend this
524 * to the given attribute name, otherwise just return name alone.
525 *
526 * @param[out] out sbuff to write the new name
527 * @param[in] da dictionary attribute to get name of
528 * @param[in] format json format structure
529 * @return length of attribute name
530 */
532{
533 fr_sbuff_t our_out;
534
535 if (!out) return 0;
536
537 our_out = FR_SBUFF(out);
538
539 if (format->attr.prefix) {
540 FR_SBUFF_IN_STRCPY_RETURN(&our_out, format->attr.prefix);
541 FR_SBUFF_IN_CHAR_RETURN(&our_out, ':');
542 }
543
544 FR_SBUFF_IN_BSTRNCPY_RETURN(&our_out, da->name, da->name_len);
545
546 FR_SBUFF_SET_RETURN(out, &our_out);
547}
548
549
550/** Verify that the options in fr_json_format_t are valid
551 *
552 * Warnings are optional, will fatal error if the format is corrupt.
553 *
554 * @param[in] format the format structure to check
555 * @param[in] verbose print out warnings if set
556 * @return true if format is good, otherwise false
557 */
558bool fr_json_format_verify(fr_json_format_t const *format, bool verbose)
559{
560 bool ret = true;
561
563
564 switch (format->output_mode) {
565 case JSON_MODE_OBJECT:
567 case JSON_MODE_ARRAY:
568 /* all options are valid */
569 return true;
571 if (format->attr.prefix) {
572 if (verbose) WARN("attribute name prefix not valid in output_mode 'array_of_values' and will be ignored");
573 ret = false;
574 }
575 if (format->value.value_is_always_array) {
576 if (verbose) WARN("'value_is_always_array' not valid in output_mode 'array_of_values' and will be ignored");
577 ret = false;
578 }
579 return ret;
581 if (format->value.value_is_always_array) {
582 if (verbose) WARN("'value_is_always_array' not valid in output_mode 'array_of_names' and will be ignored");
583 ret = false;
584 }
585 if (format->value.enum_as_int) {
586 if (verbose) WARN("'enum_as_int' not valid in output_mode 'array_of_names' and will be ignored");
587 ret = false;
588 }
589 if (format->value.always_string) {
590 if (verbose) WARN("'always_string' not valid in output_mode 'array_of_names' and will be ignored");
591 ret = false;
592 }
593 return ret;
594 default:
595 ERROR("JSON format output mode is invalid");
596 }
597
598 /* If we get here, something has gone wrong */
599 fr_assert(0);
600
601 return false;
602}
603
604#define INVALID_TYPE \
605do { \
606 fr_assert(0); \
607 fr_strerror_printf("Invalid type %s for attribute %s", fr_type_to_str(vp->vp_type), vp->da->name); \
608 return NULL; \
609} while (0)
610
611/** Returns a JSON object representation of a list of value pairs
612 *
613 * The result is a struct json_object, which should be free'd with
614 * json_object_put() by the caller. Intended to only be called by
615 * fr_json_afrom_pair_list().
616 *
617 * This function generates the "object" format, JSON_MODE_OBJECT.
618 * @see fr_json_format_s
619 *
620@verbatim
621{
622 "<attribute0>":{
623 "type":"<type0>",
624 "value":[<value0>,<value1>,<valueN>] // if value_is_always_array is true
625 }, // or
626 "<attribute1>":{
627 "type":"<type1>",
628 "value":<value0> // if value_is_always_array is false
629 // and there is only one value
630 },
631 "<attributeN>":{
632 "type":"<typeN>",
633 "value":[...]
634 }
635}
636@endverbatim
637 *
638 * @param[in] ctx Talloc context.
639 * @param[in] vps a list of value pairs.
640 * @param[in] format Formatting control, must be set.
641 * @return JSON object with the generated representation.
642 */
643static json_object *json_object_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
644 fr_json_format_t const *format)
645{
646 fr_pair_t *vp;
647 struct json_object *obj;
648 char buf[FR_DICT_ATTR_MAX_NAME_LEN + 32];
649
650 /* Check format and type */
652 fr_assert(format->output_mode == JSON_MODE_OBJECT);
653
654 MEM(obj = json_object_new_object());
655
656 for (vp = fr_pair_list_head(vps);
657 vp;
658 vp = fr_pair_list_next(vps, vp)) {
659 fr_sbuff_t attr_name;
660 struct json_object *vp_object, *values, *value, *type_name;
661
662 if (vp->vp_raw) continue;
663
664 /*
665 * Get attribute name and value.
666 */
667 fr_sbuff_init_in(&attr_name, buf, sizeof(buf) - 1);
668 if (attr_name_with_prefix(&attr_name, vp->da, format) < 0) {
669 return NULL;
670 }
671
672 switch (vp->vp_type) {
673 case FR_TYPE_LEAF:
674 if (json_afrom_value_box(ctx, &value, vp, format) < 0) {
675 fr_strerror_const("Failed to convert attribute value to JSON object");
676 error:
678
679 return NULL;
680 }
681 break;
682 /*
683 * For nested attributes we recurse. The nesting is represented
684 * as a table, either as the single value, or as an element in
685 * an array.
686 *
687 * ...
688 * "value" : { "nested_attr" : { "type" : "<nested_type>", "value" : "<nested_attr_value>" } }
689 * ...
690 *
691 * ...
692 * "value" : [ { "nested_attr" : { "type" : "<nested_type>", "value" : "<nested_attr_value>" } } ]
693 * ...
694 *
695 * The formatting of nested attributes and their structure is
696 * identical to top level attributes.
697 */
699 value = json_object_afrom_pair_list(ctx, &vp->vp_group, format);
700 break;
701
702 default:
704 }
705
706 /*
707 * Look in the table to see if we already have a key for the attribute
708 * we're working on.
709 *
710 * If we don't we create a new object in either the form:
711 *
712 * "<attribute>": {
713 * "type": "<type>",
714 * "value": [<value>] // if value_is_always_array is true
715 * // or
716 * "value": <value> // if value_is_always_array is false
717 * // and there is only one value
718 * }
719 */
720 if (!json_object_object_get_ex(obj, fr_sbuff_start(&attr_name), &vp_object)) {
721 /*
722 * Wasn't there, so create a new object for this attribute.
723 */
724 MEM(vp_object = json_object_new_object());
725 json_object_object_add(obj, fr_sbuff_start(&attr_name), vp_object);
726
727 /*
728 * Add "type" to newly created keys.
729 */
730 MEM(type_name = json_object_new_string(fr_type_to_str(vp->vp_type)));
731 json_object_object_add_ex(vp_object, "type", type_name, JSON_C_OBJECT_KEY_IS_CONSTANT);
732
733 /*
734 * Create a "value" array to hold any attribute values for this attribute...
735 */
736 if (format->value.value_is_always_array) {
737 MEM(values = json_object_new_array());
738 json_object_object_add_ex(vp_object, "value", values, JSON_C_OBJECT_KEY_IS_CONSTANT);
739 json_object_array_add(values, value);
740 continue;
741 }
742
743 /*
744 * ...or just add the value directly.
745 */
746 json_object_object_add_ex(vp_object, "value", value, JSON_C_OBJECT_KEY_IS_CONSTANT);
747
748 continue; /* Next attribute! */
749 }
750
751 /*
752 * Find the 'values' array to add the current value to.
753 */
754 if (!fr_cond_assert(json_object_object_get_ex(vp_object, "value", &values))) {
755 fr_strerror_const("Inconsistent JSON tree");
756 goto error;
757 }
758
759 /*
760 * If value_is_always_array is no set then "values" may not be an array, so it will
761 * need converting to an array to add this extra attribute.
762 */
763 if (!format->value.value_is_always_array) {
764 json_type type;
765 struct json_object *convert_value = values;
766
767 /* Check "values" type */
768 type = json_object_get_type(values);
769
770 /* It wasn't an array, so turn it into one with the old value as the first entry */
771 if (type != json_type_array) {
772 MEM(values = json_object_new_array());
773 json_object_array_add(values, json_object_get(convert_value));
774 json_object_object_del(vp_object, "value");
775 json_object_object_add_ex(vp_object, "value", values,
776 JSON_C_OBJECT_KEY_IS_CONSTANT);
777 }
778 }
779 json_object_array_add(values, value);
780 }
781
782 return obj;
783}
784
785
786/** Returns a JSON object representation of a list of value pairs
787 *
788 * The result is a struct json_object, which should be free'd with
789 * json_object_put() by the caller. Intended to only be called by
790 * fr_json_afrom_pair_list().
791 *
792 * This function generates the "simple object" format, JSON_MODE_OBJECT_SIMPLE.
793 * @see fr_json_format_s
794 *
795@verbatim
796{
797 "<attribute0>":[<value0>,<value1>,<valueN>] // if value_is_always_array is true
798 // or
799 "<attribute1>":<value0> // if value_is_always_array is false,
800 // and there is only one value
801 "<attributeN>":[<value0>,<value1>,<valueN>]
802}
803@endverbatim
804 *
805 * @param[in] ctx Talloc context.
806 * @param[in] vps a list of value pairs.
807 * @param[in] format Formatting control, must be set.
808 * @return JSON object with the generated representation.
809 */
810static json_object *json_smplobj_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
811 fr_json_format_t const *format)
812{
813 fr_pair_t *vp;
814 struct json_object *obj;
815 char buf[FR_DICT_ATTR_MAX_NAME_LEN + 32];
816 json_type type;
817
818 /* Check format and type */
821
822 MEM(obj = json_object_new_object());
823
824 for (vp = fr_pair_list_head(vps);
825 vp;
826 vp = fr_pair_list_next(vps, vp)) {
827 fr_sbuff_t attr_name;
828 struct json_object *vp_object, *value;
829 struct json_object *values = NULL;
830 bool add_single = false;
831
832 if (vp->vp_raw) continue;
833
834 /*
835 * Get attribute name and value.
836 */
837 fr_sbuff_init_in(&attr_name, buf, sizeof(buf) - 1);
838 if (attr_name_with_prefix(&attr_name, vp->da, format) < 0) {
839 return NULL;
840 }
841
842 switch (vp->vp_type) {
843 case FR_TYPE_LEAF:
844 if (json_afrom_value_box(ctx, &value, vp, format) < 0) {
845 fr_strerror_const("Failed to convert attribute value to JSON object");
847
848 return NULL;
849 }
850 break;
851 /*
852 * For nested attributes we recurse. The nesting is represented
853 * as a table, either as the single value, or as an element in
854 * an array.
855 *
856 * ...
857 * "<parent>" : { "<nested_attr>" : <nested_attr_value> }
858 * ...
859 *
860 * ...
861 * "<parent>" : [ { "<nested_attr>" : "<nested_attr_value>" } ]
862 * ...
863 *
864 * The formatting of nested attributes and their structure is
865 * identical to top level attributes.
866 */
868 value = json_smplobj_afrom_pair_list(ctx, &vp->vp_group, format);
869 break;
870
871 default:
873 }
874
875 /*
876 * See if we already have a key in the table we're working on,
877 * if not then create a new one.
878 */
879 if (!json_object_object_get_ex(obj, fr_sbuff_start(&attr_name), &vp_object)) {
880 if (format->value.value_is_always_array) {
881 /*
882 * We have been asked to ensure /all/ values are lists,
883 * even if there's only one attribute.
884 */
885 MEM(values = json_object_new_array());
886 json_object_object_add(obj, fr_sbuff_start(&attr_name), values);
887 } else {
888 /*
889 * Deal with it later on.
890 */
891 add_single = true;
892 }
893 /*
894 * If we do have the key already, get its value array.
895 */
896 } else {
897 type = json_object_get_type(vp_object);
898
899 if (type == json_type_array) {
900 values = vp_object;
901 } else {
902 /*
903 * We've seen one of these before, but didn't add
904 * it as an array the first time. Sort that out.
905 */
906 MEM(values = json_object_new_array());
907 json_object_array_add(values, json_object_get(vp_object));
908
909 /*
910 * Existing key will have refcount decremented
911 * and will be freed if this drops to zero.
912 */
913 json_object_object_add(obj, fr_sbuff_start(&attr_name), values);
914 }
915 }
916
917 if (add_single) {
918 /*
919 * Only ever used the first time adding a new
920 * attribute when "value_is_always_array" is not set.
921 */
922 json_object_object_add(obj, fr_sbuff_start(&attr_name), value);
923 } else {
924 /*
925 * Otherwise we're always appending to a JSON array.
926 */
927 json_object_array_add(values, value);
928 }
929 }
930
931 return obj;
932}
933
934
935/** Returns a JSON array representation of a list of value pairs
936 *
937 * The result is a struct json_object, which should be free'd with
938 * json_object_put() by the caller. Intended to only be called by
939 * fr_json_afrom_pair_list().
940 *
941 * This function generates the "array" format, JSON_MODE_ARRAY.
942 * @see fr_json_format_s
943 *
944 * @param[in] ctx Talloc context.
945 * @param[in] vps a list of value pairs.
946 * @param[in] format Formatting control, must be set.
947 * @return JSON object with the generated representation.
948 */
949static struct json_object *json_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
950 fr_json_format_t const *format)
951{
952 fr_pair_t *vp;
953 struct json_object *obj;
954 struct json_object *seen_attributes = NULL;
955 char buf[FR_DICT_ATTR_MAX_NAME_LEN + 32];
956
957 /* Check format and type */
959 fr_assert(format->output_mode == JSON_MODE_ARRAY);
960
961 MEM(obj = json_object_new_array());
962
963 /*
964 * If attribute values should be in a list format, then keep track
965 * of the attributes we've previously seen in a JSON object.
966 */
967 if (format->value.value_is_always_array) {
968 seen_attributes = json_object_new_object();
969 }
970
971 for (vp = fr_pair_list_head(vps);
972 vp;
973 vp = fr_pair_list_next(vps, vp)) {
974 fr_sbuff_t attr_name;
975 struct json_object *name, *value, *type_name;
976 struct json_object *values = NULL;
977 struct json_object *attrobj = NULL;
978 bool already_seen = false;
979
980 if (vp->vp_raw) continue;
981
982 /*
983 * Get attribute name and value.
984 */
985 fr_sbuff_init_in(&attr_name, buf, sizeof(buf) - 1);
986 if (attr_name_with_prefix(&attr_name, vp->da, format) < 0) {
987 return NULL;
988 }
989
990 switch (vp->vp_type) {
991 case FR_TYPE_LEAF:
992 if (json_afrom_value_box(ctx, &value, vp, format) < 0) {
993 fr_strerror_const("Failed to convert attribute value to JSON object");
995 return NULL;
996 }
997 break;
998
1000 value = json_array_afrom_pair_list(ctx, &vp->vp_group, format);
1001 break;
1002
1003 default:
1005 }
1006
1007 if (format->value.value_is_always_array) {
1008 /*
1009 * Try and find this attribute in the "seen_attributes" object. If it is
1010 * there then get the "values" array to add this attribute value to.
1011 */
1012 already_seen = json_object_object_get_ex(seen_attributes, fr_sbuff_start(&attr_name), &values);
1013 }
1014
1015 /*
1016 * If we're adding all attributes to the toplevel array, or we're adding values
1017 * to an array of an existing attribute but haven't seen it before, then we need
1018 * to create a new JSON object for this attribute.
1019 */
1020 if (!format->value.value_is_always_array || !already_seen) {
1021 /*
1022 * Create object and add it to top-level array
1023 */
1024 MEM(attrobj = json_object_new_object());
1025 json_object_array_add(obj, attrobj);
1026
1027 /*
1028 * Add the attribute name in the "name" key and the type in the "type" key
1029 */
1030 MEM(name = json_object_new_string(fr_sbuff_start(&attr_name)));
1031 json_object_object_add_ex(attrobj, "name", name, JSON_C_OBJECT_KEY_IS_CONSTANT);
1032
1033 MEM(type_name = json_object_new_string(fr_type_to_str(vp->vp_type)));
1034 json_object_object_add_ex(attrobj, "type", type_name, JSON_C_OBJECT_KEY_IS_CONSTANT);
1035 }
1036
1037 if (format->value.value_is_always_array) {
1038 /*
1039 * We're adding values to an array for the first copy of this attribute
1040 * that we saw. First time around we need to create an array.
1041 */
1042 if (!already_seen) {
1043 MEM(values = json_object_new_array());
1044 /*
1045 * Add "value":[] key to the attribute object
1046 */
1047 json_object_object_add_ex(attrobj, "value", values, JSON_C_OBJECT_KEY_IS_CONSTANT);
1048
1049 /*
1050 * Also add to "seen_attributes" to check later
1051 */
1052 json_object_object_add(seen_attributes, fr_sbuff_start(&attr_name), json_object_get(values));
1053 }
1054
1055 /*
1056 * Always add the value to the respective "values" array.
1057 */
1058 json_object_array_add(values, value);
1059 } else {
1060 /*
1061 * This is simpler; just add a "value": key to the attribute object.
1062 */
1063 json_object_object_add_ex(attrobj, "value", value, JSON_C_OBJECT_KEY_IS_CONSTANT);
1064 }
1065
1066 }
1067
1068 /*
1069 * No longer need the "seen_attributes" object, it was just used for tracking.
1070 */
1071 if (format->value.value_is_always_array) {
1072 json_object_put_assert(seen_attributes);
1073 }
1074
1075 return obj;
1076}
1077
1078
1079/** Returns a JSON array of a list of value pairs
1080 *
1081 * The result is a struct json_object, which should be free'd with
1082 * json_object_put() by the caller. Intended to only be called by
1083 * fr_json_afrom_pair_list().
1084 *
1085 * This function generates the "array_of_values" format,
1086 * JSON_MODE_ARRAY_OF_VALUES, listing just the attribute values.
1087 * @see fr_json_format_s
1088 *
1089 * @param[in] ctx Talloc context.
1090 * @param[in] vps a list of value pairs.
1091 * @param[in] format Formatting control, must be set.
1092 * @return JSON object with the generated representation.
1093 */
1094static struct json_object *json_value_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
1095 fr_json_format_t const *format)
1096{
1097 fr_pair_t *vp;
1098 struct json_object *obj;
1099
1100 /* Check format and type */
1103
1104 MEM(obj = json_object_new_array());
1105
1106 /*
1107 * This array format is very simple - just add all the
1108 * attribute values to the array in order.
1109 */
1110 for (vp = fr_pair_list_head(vps);
1111 vp;
1112 vp = fr_pair_list_next(vps, vp)) {
1113 struct json_object *value;
1114
1115 if (vp->vp_raw) continue;
1116
1117 switch (vp->vp_type) {
1118 case FR_TYPE_LEAF:
1119 if (json_afrom_value_box(ctx, &value, vp, format) < 0) {
1120 fr_strerror_const("Failed to convert attribute value to JSON object");
1122 return NULL;
1123 }
1124 break;
1125
1126 case FR_TYPE_STRUCTURAL:
1127 value = json_value_array_afrom_pair_list(ctx, &vp->vp_group, format);
1128 break;
1129
1130 default:
1132 }
1133
1134 json_object_array_add(obj, value);
1135 }
1136
1137 return obj;
1138}
1139
1140
1141/** Returns a JSON array of a list of value pairs
1142 *
1143 * The result is a struct json_object, which should be free'd with
1144 * json_object_put() by the caller. Intended to only be called by
1145 * fr_json_afrom_pair_list().
1146 *
1147 * This function generates the "array_of_names" format,
1148 * JSON_MODE_ARRAY_OF_NAMES, listing just the attribute names.
1149 * @see fr_json_format_s
1150 *
1151 * @param[in] ctx Talloc context.
1152 * @param[in] vps a list of value pairs.
1153 * @param[in] format Formatting control, must be set.
1154 * @return JSON object with the generated representation.
1155 */
1156static struct json_object *json_attr_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
1157 fr_json_format_t const *format)
1158{
1159 fr_pair_t *vp;
1160 struct json_object *obj;
1161 char buf[FR_DICT_ATTR_MAX_NAME_LEN + 32];
1162
1163 /* Check format and type */
1165 fr_assert(format->output_mode == JSON_MODE_ARRAY_OF_NAMES);
1166
1167 MEM(obj = json_object_new_array());
1168
1169 /*
1170 * Add all the attribute names to the array in order.
1171 */
1172 for (vp = fr_pair_list_head(vps);
1173 vp;
1174 vp = fr_pair_list_next(vps, vp)) {
1175 struct json_object *value;
1176 fr_sbuff_t attr_name;
1177
1178 if (vp->vp_raw) continue;
1179
1180 fr_sbuff_init_in(&attr_name, buf, sizeof(buf) - 1);
1181 if (attr_name_with_prefix(&attr_name, vp->da, format) < 0) {
1182 return NULL;
1183 }
1184 value = json_object_new_string(fr_sbuff_start(&attr_name));
1185
1186 switch (vp->vp_type) {
1187 case FR_TYPE_LEAF:
1188 break;
1189
1190 case FR_TYPE_STRUCTURAL:
1191 json_object_array_add(obj, value);
1192 value = json_attr_array_afrom_pair_list(ctx, &vp->vp_group, format);
1193 break;
1194
1195 default:
1197 }
1198
1199 json_object_array_add(obj, value);
1200 }
1201
1202 return obj;
1203}
1204
1205
1206/** Returns a JSON string of a list of value pairs
1207 *
1208 * The result is a talloc-ed string, freeing the string is
1209 * the responsibility of the caller.
1210 *
1211 * The 'format' struct contains settings to configure the output
1212 * JSON document format.
1213 * @see fr_json_format_s
1214 *
1215 * Default output, when format is NULL, is:
1216@verbatim
1217{
1218 "<attribute0>":{
1219 "type":"<type0>",
1220 "value":[<value0>,<value1>,<valueN>]
1221 },
1222 "<attribute1>":{
1223 "type":"<type1>",
1224 "value":[...]
1225 },
1226 "<attributeN>":{
1227 "type":"<typeN>",
1228 "value":[...]
1229 }
1230}
1231@endverbatim
1232 *
1233 * @param[in] ctx Talloc context.
1234 * @param[in] vps a list of value pairs.
1235 * @param[in] format Formatting control, can be NULL to use default format.
1236 * @return JSON string representation of the value pairs
1237 */
1238char *fr_json_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
1239 fr_json_format_t const *format)
1240{
1241 struct json_object *obj = NULL;
1242 const char *p;
1243 char *out;
1244
1246
1247 switch (format->output_mode) {
1248 case JSON_MODE_OBJECT:
1249 MEM(obj = json_object_afrom_pair_list(ctx, vps, format));
1250 break;
1252 MEM(obj = json_smplobj_afrom_pair_list(ctx, vps, format));
1253 break;
1254 case JSON_MODE_ARRAY:
1255 MEM(obj = json_array_afrom_pair_list(ctx, vps, format));
1256 break;
1259 break;
1261 MEM(obj = json_attr_array_afrom_pair_list(ctx, vps, format));
1262 break;
1263 default:
1264 /* This should never happen */
1265 fr_assert(0);
1266 }
1267
1268 /*
1269 * p is a buff inside obj, and will be freed
1270 * when it is freed.
1271 */
1272 MEM(p = json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN));
1273 MEM(out = talloc_typed_strdup(ctx, p));
1274
1275 /*
1276 * Free the JSON structure, it's not needed any more
1277 */
1279
1280 return out;
1281}
static int const char char buffer[256]
Definition acutest.h:576
#define fr_base16_encode(_out, _in)
Definition base16.h:57
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define unlikely(_x)
Definition build.h:383
#define NUM_ELEMENTS(_t)
Definition build.h:339
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:662
#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
Definition cf_parse.h:284
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Definition cf_parse.h:313
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:599
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:131
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition debug.h:208
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:237
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.
Definition dict_util.c:3393
ssize_t fr_dict_valid_name(char const *name, ssize_t len)
Definition dict_util.c:4664
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3439
char const * name
Enum name.
Definition dict.h:234
#define FR_DICT_ATTR_MAX_NAME_LEN
Maximum length of a attribute name.
Definition dict.h:480
Value of an enumerated attribute.
Definition dict.h:233
Test enumeration values.
Definition dict_test.h:92
@ JSON_MODE_ARRAY
Definition base.h:61
@ JSON_MODE_OBJECT
Definition base.h:59
@ JSON_MODE_ARRAY_OF_NAMES
Definition base.h:63
@ JSON_MODE_OBJECT_SIMPLE
Definition base.h:60
@ JSON_MODE_ARRAY_OF_VALUES
Definition base.h:62
fr_json_format_attr_t attr
Formatting options for attribute names.
Definition base.h:225
char const * prefix
Prefix to add to all attribute names.
Definition base.h:89
Attribute formatting options for fr_json_afrom_pair_list()
Definition base.h:88
JSON document formatting options.
Definition base.h:219
Value formatting options for fr_json_afrom_pair_list()
Definition base.h:147
static json_object * json_smplobj_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.
Definition json.c:810
static fr_json_format_t const default_json_format
Definition json.c:45
static void json_object_put_assert(json_object *obj)
Definition json.c:72
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.
Definition json.c:1238
size_t fr_json_format_table_len
Definition json.c:43
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.
Definition json.c:1094
static conf_parser_t const json_format_value_config[]
Definition json.c:56
json_object * json_object_from_value_box(fr_value_box_t const *data)
Convert boxed value_box to a JSON object.
Definition json.c:193
static conf_parser_t const json_format_attr_config[]
Definition json.c:51
fr_slen_t fr_json_str_from_value(fr_sbuff_t *out, fr_value_box_t *vb, bool include_quotes)
Print a value box as its equivalent JSON format without going via a struct json_object (in most cases...
Definition json.c:279
#define INVALID_TYPE
Definition json.c:604
static int json_afrom_value_box(TALLOC_CTX *ctx, json_object **out, fr_pair_t *vp, fr_json_format_t const *format)
Convert fr_pair_t into a JSON object.
Definition json.c:485
conf_parser_t const fr_json_format_config[]
Definition json.c:63
void fr_json_version_print(void)
Print JSON-C version.
Definition json.c:458
fr_table_num_sorted_t const fr_json_format_table[]
Definition json.c:36
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.
Definition json.c:949
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.
Definition json.c:643
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.
Definition json.c:1156
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.
Definition json.c:96
bool fr_json_format_verify(fr_json_format_t const *format, bool verbose)
Verify that the options in fr_json_format_t are valid.
Definition json.c:558
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.
Definition json.c:531
unsigned short uint16_t
@ 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.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
ssize_t fr_slen_t
#define UINT8_MAX
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.
Definition pair.c:3064
#define fr_assert(_expr)
Definition rad_assert.h:38
#define WARN(fmt,...)
Definition radclient.h:47
#define INFO(fmt,...)
Definition radict.c:54
static char const * name
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
Definition sbuff.c:1456
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN(_start, _len_or_end)
#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_used(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
fr_aka_sim_id_type_t type
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:467
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.
Definition pair_inline.c:69
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:42
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
@ FR_TYPE_ATTR
A contains an attribute reference.
Definition types.h:83
#define FR_TYPE_INTERNAL
Definition types.h:317
#define FR_TYPE_STRUCTURAL
Definition types.h:314
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:452
#define FR_TYPE_LEAF
Definition types.h:315
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.
Definition value.c:5668
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.
Definition value.c:3671
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.
Definition value.c:4086
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4069
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.
Definition value.c:4513
static fr_slen_t data
Definition value.h:1291
#define FR_VALUE_BOX_INITIALISER_NULL(_vb)
A static initialiser for stack/globally allocated boxes.
Definition value.h:510
#define fr_value_box(_box, _var, _tainted)
Automagically fill in a box, determining the value type from the type of the C variable.
Definition value.h:897
int format(printf, 5, 0))
static size_t char ** out
Definition value.h:1023