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: e90ea072c88da82d354740724ec29a9a8b1c7a5b $
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;
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) {
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 {
433 fr_slen_t slen;
434
435 if (include_quotes) FR_SBUFF_IN_CHAR_RETURN(&our_out, '"');
436 slen = fr_value_box_print(&our_out, vb, NULL);
437 if (include_quotes) FR_SBUFF_IN_CHAR_RETURN(&our_out, '"');
438 if (slen < 0) return slen;
439 }
440 break;
441
443 fr_strerror_const("Structural boxes not yet supported");
444 return -1;
445
446 case FR_TYPE_VOID:
448 case FR_TYPE_MAX:
449 fr_strerror_printf("Box type %s cannot be converted to string", fr_type_to_str(vb->type));
450 return -1;
451 }
452
453 return fr_sbuff_set(out, &our_out);
454}
455
456/** Print JSON-C version
457 *
458 */
460{
461#ifdef HAVE_JSON_C_VERSION
462 INFO("libfreeradius-json: json-c version: %s", json_c_version());
463#else
464 INFO("libfreeradius-json: json-c version: Unknown (less than 0.10) - Please upgrade");
465#endif
466}
467
468
469/** Convert fr_pair_t into a JSON object
470 *
471 * If format.value.enum_as_int is set, and the given VP is an enum
472 * value, the integer value is returned as a json_object rather
473 * than the text representation.
474 *
475 * If format.value.always_string is set then a numeric value pair
476 * will be returned as a JSON string object.
477 *
478 * @param[in] ctx Talloc context.
479 * @param[out] out returned json object.
480 * @param[in] vp to get the value of.
481 * @param[in] format format definition, or NULL.
482 * @return
483 * - 1 if 'out' is the integer enum value, 0 otherwise
484 * - -1 on error.
485 */
486static int json_afrom_value_box(TALLOC_CTX *ctx, json_object **out,
487 fr_pair_t *vp, fr_json_format_t const *format)
488{
489 struct json_object *obj;
490 fr_value_box_t const *vb;
492 int is_enum = 0;
493
494 fr_assert(vp);
495
496 vb = &vp->data;
497
498 if (format && format->value.enum_as_int) {
499 is_enum = fr_pair_value_enum_box(&vb, vp);
500 fr_assert(is_enum >= 0);
501 }
502
503 if (format && format->value.always_string) {
504 if (fr_value_box_cast(ctx, &vb_str, FR_TYPE_STRING, NULL, vb) < 0) {
505 return -1;
506 }
507
508 vb = &vb_str;
509 }
510
512
513 if (format && format->value.always_string) {
514 fr_value_box_clear(&vb_str);
515 }
516
517 *out = obj;
518 return is_enum;
519}
520
521
522/** Get attribute name with optional prefix
523 *
524 * If the format "attr.prefix" string is set then prepend this
525 * to the given attribute name, otherwise just return name alone.
526 *
527 * @param[out] out sbuff to write the new name
528 * @param[in] da dictionary attribute to get name of
529 * @param[in] format json format structure
530 * @return length of attribute name
531 */
533{
534 fr_sbuff_t our_out;
535
536 if (!out) return 0;
537
538 our_out = FR_SBUFF(out);
539
540 if (format->attr.prefix) {
541 FR_SBUFF_IN_STRCPY_RETURN(&our_out, format->attr.prefix);
542 FR_SBUFF_IN_CHAR_RETURN(&our_out, ':');
543 }
544
545 FR_SBUFF_IN_BSTRNCPY_RETURN(&our_out, da->name, da->name_len);
546
547 FR_SBUFF_SET_RETURN(out, &our_out);
548}
549
550
551/** Verify that the options in fr_json_format_t are valid
552 *
553 * Warnings are optional, will fatal error if the format is corrupt.
554 *
555 * @param[in] format the format structure to check
556 * @param[in] verbose print out warnings if set
557 * @return true if format is good, otherwise false
558 */
559bool fr_json_format_verify(fr_json_format_t const *format, bool verbose)
560{
561 bool ret = true;
562
564
565 switch (format->output_mode) {
566 case JSON_MODE_OBJECT:
568 case JSON_MODE_ARRAY:
569 /* all options are valid */
570 return true;
572 if (format->attr.prefix) {
573 if (verbose) WARN("attribute name prefix not valid in output_mode 'array_of_values' and will be ignored");
574 ret = false;
575 }
576 if (format->value.value_is_always_array) {
577 if (verbose) WARN("'value_is_always_array' not valid in output_mode 'array_of_values' and will be ignored");
578 ret = false;
579 }
580 return ret;
582 if (format->value.value_is_always_array) {
583 if (verbose) WARN("'value_is_always_array' not valid in output_mode 'array_of_names' and will be ignored");
584 ret = false;
585 }
586 if (format->value.enum_as_int) {
587 if (verbose) WARN("'enum_as_int' not valid in output_mode 'array_of_names' and will be ignored");
588 ret = false;
589 }
590 if (format->value.always_string) {
591 if (verbose) WARN("'always_string' not valid in output_mode 'array_of_names' and will be ignored");
592 ret = false;
593 }
594 return ret;
595 default:
596 ERROR("JSON format output mode is invalid");
597 }
598
599 /* If we get here, something has gone wrong */
600 fr_assert(0);
601
602 return false;
603}
604
605#define INVALID_TYPE \
606do { \
607 fr_assert(0); \
608 fr_strerror_printf("Invalid type %s for attribute %s", fr_type_to_str(vp->vp_type), vp->da->name); \
609 return NULL; \
610} while (0)
611
612/** Returns a JSON object representation of a list of value pairs
613 *
614 * The result is a struct json_object, which should be free'd with
615 * json_object_put() by the caller. Intended to only be called by
616 * fr_json_afrom_pair_list().
617 *
618 * This function generates the "object" format, JSON_MODE_OBJECT.
619 * @see fr_json_format_s
620 *
621@verbatim
622{
623 "<attribute0>":{
624 "type":"<type0>",
625 "value":[<value0>,<value1>,<valueN>] // if value_is_always_array is true
626 }, // or
627 "<attribute1>":{
628 "type":"<type1>",
629 "value":<value0> // if value_is_always_array is false
630 // and there is only one value
631 },
632 "<attributeN>":{
633 "type":"<typeN>",
634 "value":[...]
635 }
636}
637@endverbatim
638 *
639 * @param[in] ctx Talloc context.
640 * @param[in] vps a list of value pairs.
641 * @param[in] format Formatting control, must be set.
642 * @return JSON object with the generated representation.
643 */
644static json_object *json_object_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
645 fr_json_format_t const *format)
646{
647 fr_pair_t *vp;
648 struct json_object *obj;
649 char buf[FR_DICT_ATTR_MAX_NAME_LEN + 32];
650
651 /* Check format and type */
653 fr_assert(format->output_mode == JSON_MODE_OBJECT);
654
655 MEM(obj = json_object_new_object());
656
657 for (vp = fr_pair_list_head(vps);
658 vp;
659 vp = fr_pair_list_next(vps, vp)) {
660 fr_sbuff_t attr_name;
661 struct json_object *vp_object, *values, *value, *type_name;
662
663 if (vp->vp_raw) continue;
664
665 /*
666 * Get attribute name and value.
667 */
668 fr_sbuff_init_in(&attr_name, buf, sizeof(buf) - 1);
669 if (attr_name_with_prefix(&attr_name, vp->da, format) < 0) {
670 return NULL;
671 }
672
673 switch (vp->vp_type) {
674 case FR_TYPE_LEAF:
675 if (json_afrom_value_box(ctx, &value, vp, format) < 0) {
676 fr_strerror_const("Failed to convert attribute value to JSON object");
677 error:
679
680 return NULL;
681 }
682 break;
683 /*
684 * For nested attributes we recurse. The nesting is represented
685 * as a table, either as the single value, or as an element in
686 * an array.
687 *
688 * ...
689 * "value" : { "nested_attr" : { "type" : "<nested_type>", "value" : "<nested_attr_value>" } }
690 * ...
691 *
692 * ...
693 * "value" : [ { "nested_attr" : { "type" : "<nested_type>", "value" : "<nested_attr_value>" } } ]
694 * ...
695 *
696 * The formatting of nested attributes and their structure is
697 * identical to top level attributes.
698 */
700 value = json_object_afrom_pair_list(ctx, &vp->vp_group, format);
701 break;
702
703 default:
705 }
706
707 /*
708 * Look in the table to see if we already have a key for the attribute
709 * we're working on.
710 *
711 * If we don't we create a new object in either the form:
712 *
713 * "<attribute>": {
714 * "type": "<type>",
715 * "value": [<value>] // if value_is_always_array is true
716 * // or
717 * "value": <value> // if value_is_always_array is false
718 * // and there is only one value
719 * }
720 */
721 if (!json_object_object_get_ex(obj, fr_sbuff_start(&attr_name), &vp_object)) {
722 /*
723 * Wasn't there, so create a new object for this attribute.
724 */
725 MEM(vp_object = json_object_new_object());
726 json_object_object_add(obj, fr_sbuff_start(&attr_name), vp_object);
727
728 /*
729 * Add "type" to newly created keys.
730 */
731 MEM(type_name = json_object_new_string(fr_type_to_str(vp->vp_type)));
732 json_object_object_add_ex(vp_object, "type", type_name, JSON_C_OBJECT_KEY_IS_CONSTANT);
733
734 /*
735 * Create a "value" array to hold any attribute values for this attribute...
736 */
737 if (format->value.value_is_always_array) {
738 MEM(values = json_object_new_array());
739 json_object_object_add_ex(vp_object, "value", values, JSON_C_OBJECT_KEY_IS_CONSTANT);
740 json_object_array_add(values, value);
741 continue;
742 }
743
744 /*
745 * ...or just add the value directly.
746 */
747 json_object_object_add_ex(vp_object, "value", value, JSON_C_OBJECT_KEY_IS_CONSTANT);
748
749 continue; /* Next attribute! */
750 }
751
752 /*
753 * Find the 'values' array to add the current value to.
754 */
755 if (!fr_cond_assert(json_object_object_get_ex(vp_object, "value", &values))) {
756 fr_strerror_const("Inconsistent JSON tree");
757 goto error;
758 }
759
760 /*
761 * If value_is_always_array is no set then "values" may not be an array, so it will
762 * need converting to an array to add this extra attribute.
763 */
764 if (!format->value.value_is_always_array) {
765 json_type type;
766 struct json_object *convert_value = values;
767
768 /* Check "values" type */
769 type = json_object_get_type(values);
770
771 /* It wasn't an array, so turn it into one with the old value as the first entry */
772 if (type != json_type_array) {
773 MEM(values = json_object_new_array());
774 json_object_array_add(values, json_object_get(convert_value));
775 json_object_object_del(vp_object, "value");
776 json_object_object_add_ex(vp_object, "value", values,
777 JSON_C_OBJECT_KEY_IS_CONSTANT);
778 }
779 }
780 json_object_array_add(values, value);
781 }
782
783 return obj;
784}
785
786
787/** Returns a JSON object representation of a list of value pairs
788 *
789 * The result is a struct json_object, which should be free'd with
790 * json_object_put() by the caller. Intended to only be called by
791 * fr_json_afrom_pair_list().
792 *
793 * This function generates the "simple object" format, JSON_MODE_OBJECT_SIMPLE.
794 * @see fr_json_format_s
795 *
796@verbatim
797{
798 "<attribute0>":[<value0>,<value1>,<valueN>] // if value_is_always_array is true
799 // or
800 "<attribute1>":<value0> // if value_is_always_array is false,
801 // and there is only one value
802 "<attributeN>":[<value0>,<value1>,<valueN>]
803}
804@endverbatim
805 *
806 * @param[in] ctx Talloc context.
807 * @param[in] vps a list of value pairs.
808 * @param[in] format Formatting control, must be set.
809 * @return JSON object with the generated representation.
810 */
811static json_object *json_smplobj_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
812 fr_json_format_t const *format)
813{
814 fr_pair_t *vp;
815 struct json_object *obj;
816 char buf[FR_DICT_ATTR_MAX_NAME_LEN + 32];
817 json_type type;
818
819 /* Check format and type */
822
823 MEM(obj = json_object_new_object());
824
825 for (vp = fr_pair_list_head(vps);
826 vp;
827 vp = fr_pair_list_next(vps, vp)) {
828 fr_sbuff_t attr_name;
829 struct json_object *vp_object, *value;
830 struct json_object *values = NULL;
831 bool add_single = false;
832
833 if (vp->vp_raw) continue;
834
835 /*
836 * Get attribute name and value.
837 */
838 fr_sbuff_init_in(&attr_name, buf, sizeof(buf) - 1);
839 if (attr_name_with_prefix(&attr_name, vp->da, format) < 0) {
840 return NULL;
841 }
842
843 switch (vp->vp_type) {
844 case FR_TYPE_LEAF:
845 if (json_afrom_value_box(ctx, &value, vp, format) < 0) {
846 fr_strerror_const("Failed to convert attribute value to JSON object");
848
849 return NULL;
850 }
851 break;
852 /*
853 * For nested attributes we recurse. The nesting is represented
854 * as a table, either as the single value, or as an element in
855 * an array.
856 *
857 * ...
858 * "<parent>" : { "<nested_attr>" : <nested_attr_value> }
859 * ...
860 *
861 * ...
862 * "<parent>" : [ { "<nested_attr>" : "<nested_attr_value>" } ]
863 * ...
864 *
865 * The formatting of nested attributes and their structure is
866 * identical to top level attributes.
867 */
869 value = json_smplobj_afrom_pair_list(ctx, &vp->vp_group, format);
870 break;
871
872 default:
874 }
875
876 /*
877 * See if we already have a key in the table we're working on,
878 * if not then create a new one.
879 */
880 if (!json_object_object_get_ex(obj, fr_sbuff_start(&attr_name), &vp_object)) {
881 if (format->value.value_is_always_array) {
882 /*
883 * We have been asked to ensure /all/ values are lists,
884 * even if there's only one attribute.
885 */
886 MEM(values = json_object_new_array());
887 json_object_object_add(obj, fr_sbuff_start(&attr_name), values);
888 } else {
889 /*
890 * Deal with it later on.
891 */
892 add_single = true;
893 }
894 /*
895 * If we do have the key already, get its value array.
896 */
897 } else {
898 type = json_object_get_type(vp_object);
899
900 if (type == json_type_array) {
901 values = vp_object;
902 } else {
903 /*
904 * We've seen one of these before, but didn't add
905 * it as an array the first time. Sort that out.
906 */
907 MEM(values = json_object_new_array());
908 json_object_array_add(values, json_object_get(vp_object));
909
910 /*
911 * Existing key will have refcount decremented
912 * and will be freed if this drops to zero.
913 */
914 json_object_object_add(obj, fr_sbuff_start(&attr_name), values);
915 }
916 }
917
918 if (add_single) {
919 /*
920 * Only ever used the first time adding a new
921 * attribute when "value_is_always_array" is not set.
922 */
923 json_object_object_add(obj, fr_sbuff_start(&attr_name), value);
924 } else {
925 /*
926 * Otherwise we're always appending to a JSON array.
927 */
928 json_object_array_add(values, value);
929 }
930 }
931
932 return obj;
933}
934
935
936/** Returns a JSON array representation of a list of value pairs
937 *
938 * The result is a struct json_object, which should be free'd with
939 * json_object_put() by the caller. Intended to only be called by
940 * fr_json_afrom_pair_list().
941 *
942 * This function generates the "array" format, JSON_MODE_ARRAY.
943 * @see fr_json_format_s
944 *
945 * @param[in] ctx Talloc context.
946 * @param[in] vps a list of value pairs.
947 * @param[in] format Formatting control, must be set.
948 * @return JSON object with the generated representation.
949 */
950static struct json_object *json_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
951 fr_json_format_t const *format)
952{
953 fr_pair_t *vp;
954 struct json_object *obj;
955 struct json_object *seen_attributes = NULL;
956 char buf[FR_DICT_ATTR_MAX_NAME_LEN + 32];
957
958 /* Check format and type */
960 fr_assert(format->output_mode == JSON_MODE_ARRAY);
961
962 MEM(obj = json_object_new_array());
963
964 /*
965 * If attribute values should be in a list format, then keep track
966 * of the attributes we've previously seen in a JSON object.
967 */
968 if (format->value.value_is_always_array) {
969 seen_attributes = json_object_new_object();
970 }
971
972 for (vp = fr_pair_list_head(vps);
973 vp;
974 vp = fr_pair_list_next(vps, vp)) {
975 fr_sbuff_t attr_name;
976 struct json_object *name, *value, *type_name;
977 struct json_object *values = NULL;
978 struct json_object *attrobj = NULL;
979 bool already_seen = false;
980
981 if (vp->vp_raw) continue;
982
983 /*
984 * Get attribute name and value.
985 */
986 fr_sbuff_init_in(&attr_name, buf, sizeof(buf) - 1);
987 if (attr_name_with_prefix(&attr_name, vp->da, format) < 0) {
988 return NULL;
989 }
990
991 switch (vp->vp_type) {
992 case FR_TYPE_LEAF:
993 if (json_afrom_value_box(ctx, &value, vp, format) < 0) {
994 fr_strerror_const("Failed to convert attribute value to JSON object");
996 return NULL;
997 }
998 break;
999
1000 case FR_TYPE_STRUCTURAL:
1001 value = json_array_afrom_pair_list(ctx, &vp->vp_group, format);
1002 break;
1003
1004 default:
1006 }
1007
1008 if (format->value.value_is_always_array) {
1009 /*
1010 * Try and find this attribute in the "seen_attributes" object. If it is
1011 * there then get the "values" array to add this attribute value to.
1012 */
1013 already_seen = json_object_object_get_ex(seen_attributes, fr_sbuff_start(&attr_name), &values);
1014 }
1015
1016 /*
1017 * If we're adding all attributes to the toplevel array, or we're adding values
1018 * to an array of an existing attribute but haven't seen it before, then we need
1019 * to create a new JSON object for this attribute.
1020 */
1021 if (!format->value.value_is_always_array || !already_seen) {
1022 /*
1023 * Create object and add it to top-level array
1024 */
1025 MEM(attrobj = json_object_new_object());
1026 json_object_array_add(obj, attrobj);
1027
1028 /*
1029 * Add the attribute name in the "name" key and the type in the "type" key
1030 */
1031 MEM(name = json_object_new_string(fr_sbuff_start(&attr_name)));
1032 json_object_object_add_ex(attrobj, "name", name, JSON_C_OBJECT_KEY_IS_CONSTANT);
1033
1034 MEM(type_name = json_object_new_string(fr_type_to_str(vp->vp_type)));
1035 json_object_object_add_ex(attrobj, "type", type_name, JSON_C_OBJECT_KEY_IS_CONSTANT);
1036 }
1037
1038 if (format->value.value_is_always_array) {
1039 /*
1040 * We're adding values to an array for the first copy of this attribute
1041 * that we saw. First time around we need to create an array.
1042 */
1043 if (!already_seen) {
1044 MEM(values = json_object_new_array());
1045 /*
1046 * Add "value":[] key to the attribute object
1047 */
1048 json_object_object_add_ex(attrobj, "value", values, JSON_C_OBJECT_KEY_IS_CONSTANT);
1049
1050 /*
1051 * Also add to "seen_attributes" to check later
1052 */
1053 json_object_object_add(seen_attributes, fr_sbuff_start(&attr_name), json_object_get(values));
1054 }
1055
1056 /*
1057 * Always add the value to the respective "values" array.
1058 */
1059 json_object_array_add(values, value);
1060 } else {
1061 /*
1062 * This is simpler; just add a "value": key to the attribute object.
1063 */
1064 json_object_object_add_ex(attrobj, "value", value, JSON_C_OBJECT_KEY_IS_CONSTANT);
1065 }
1066
1067 }
1068
1069 /*
1070 * No longer need the "seen_attributes" object, it was just used for tracking.
1071 */
1072 if (format->value.value_is_always_array) {
1073 json_object_put_assert(seen_attributes);
1074 }
1075
1076 return obj;
1077}
1078
1079
1080/** Returns a JSON array of a list of value pairs
1081 *
1082 * The result is a struct json_object, which should be free'd with
1083 * json_object_put() by the caller. Intended to only be called by
1084 * fr_json_afrom_pair_list().
1085 *
1086 * This function generates the "array_of_values" format,
1087 * JSON_MODE_ARRAY_OF_VALUES, listing just the attribute values.
1088 * @see fr_json_format_s
1089 *
1090 * @param[in] ctx Talloc context.
1091 * @param[in] vps a list of value pairs.
1092 * @param[in] format Formatting control, must be set.
1093 * @return JSON object with the generated representation.
1094 */
1095static struct json_object *json_value_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
1096 fr_json_format_t const *format)
1097{
1098 fr_pair_t *vp;
1099 struct json_object *obj;
1100
1101 /* Check format and type */
1104
1105 MEM(obj = json_object_new_array());
1106
1107 /*
1108 * This array format is very simple - just add all the
1109 * attribute values to the array in order.
1110 */
1111 for (vp = fr_pair_list_head(vps);
1112 vp;
1113 vp = fr_pair_list_next(vps, vp)) {
1114 struct json_object *value;
1115
1116 if (vp->vp_raw) continue;
1117
1118 switch (vp->vp_type) {
1119 case FR_TYPE_LEAF:
1120 if (json_afrom_value_box(ctx, &value, vp, format) < 0) {
1121 fr_strerror_const("Failed to convert attribute value to JSON object");
1123 return NULL;
1124 }
1125 break;
1126
1127 case FR_TYPE_STRUCTURAL:
1128 value = json_value_array_afrom_pair_list(ctx, &vp->vp_group, format);
1129 break;
1130
1131 default:
1133 }
1134
1135 json_object_array_add(obj, value);
1136 }
1137
1138 return obj;
1139}
1140
1141
1142/** Returns a JSON array of a list of value pairs
1143 *
1144 * The result is a struct json_object, which should be free'd with
1145 * json_object_put() by the caller. Intended to only be called by
1146 * fr_json_afrom_pair_list().
1147 *
1148 * This function generates the "array_of_names" format,
1149 * JSON_MODE_ARRAY_OF_NAMES, listing just the attribute names.
1150 * @see fr_json_format_s
1151 *
1152 * @param[in] ctx Talloc context.
1153 * @param[in] vps a list of value pairs.
1154 * @param[in] format Formatting control, must be set.
1155 * @return JSON object with the generated representation.
1156 */
1157static struct json_object *json_attr_array_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
1158 fr_json_format_t const *format)
1159{
1160 fr_pair_t *vp;
1161 struct json_object *obj;
1162 char buf[FR_DICT_ATTR_MAX_NAME_LEN + 32];
1163
1164 /* Check format and type */
1166 fr_assert(format->output_mode == JSON_MODE_ARRAY_OF_NAMES);
1167
1168 MEM(obj = json_object_new_array());
1169
1170 /*
1171 * Add all the attribute names to the array in order.
1172 */
1173 for (vp = fr_pair_list_head(vps);
1174 vp;
1175 vp = fr_pair_list_next(vps, vp)) {
1176 struct json_object *value;
1177 fr_sbuff_t attr_name;
1178
1179 if (vp->vp_raw) continue;
1180
1181 fr_sbuff_init_in(&attr_name, buf, sizeof(buf) - 1);
1182 if (attr_name_with_prefix(&attr_name, vp->da, format) < 0) {
1183 return NULL;
1184 }
1185 value = json_object_new_string(fr_sbuff_start(&attr_name));
1186
1187 switch (vp->vp_type) {
1188 case FR_TYPE_LEAF:
1189 break;
1190
1191 case FR_TYPE_STRUCTURAL:
1192 json_object_array_add(obj, value);
1193 value = json_attr_array_afrom_pair_list(ctx, &vp->vp_group, format);
1194 break;
1195
1196 default:
1198 }
1199
1200 json_object_array_add(obj, value);
1201 }
1202
1203 return obj;
1204}
1205
1206
1207/** Returns a JSON string of a list of value pairs
1208 *
1209 * The result is a talloc-ed string, freeing the string is
1210 * the responsibility of the caller.
1211 *
1212 * The 'format' struct contains settings to configure the output
1213 * JSON document format.
1214 * @see fr_json_format_s
1215 *
1216 * Default output, when format is NULL, is:
1217@verbatim
1218{
1219 "<attribute0>":{
1220 "type":"<type0>",
1221 "value":[<value0>,<value1>,<valueN>]
1222 },
1223 "<attribute1>":{
1224 "type":"<type1>",
1225 "value":[...]
1226 },
1227 "<attributeN>":{
1228 "type":"<typeN>",
1229 "value":[...]
1230 }
1231}
1232@endverbatim
1233 *
1234 * @param[in] ctx Talloc context.
1235 * @param[in] vps a list of value pairs.
1236 * @param[in] format Formatting control, can be NULL to use default format.
1237 * @return JSON string representation of the value pairs
1238 */
1239char *fr_json_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps,
1240 fr_json_format_t const *format)
1241{
1242 struct json_object *obj = NULL;
1243 const char *p;
1244 char *out;
1245
1247
1248 switch (format->output_mode) {
1249 case JSON_MODE_OBJECT:
1250 MEM(obj = json_object_afrom_pair_list(ctx, vps, format));
1251 break;
1253 MEM(obj = json_smplobj_afrom_pair_list(ctx, vps, format));
1254 break;
1255 case JSON_MODE_ARRAY:
1256 MEM(obj = json_array_afrom_pair_list(ctx, vps, format));
1257 break;
1260 break;
1262 MEM(obj = json_attr_array_afrom_pair_list(ctx, vps, format));
1263 break;
1264 default:
1265 /* This should never happen */
1266 fr_assert(0);
1267 }
1268
1269 /*
1270 * p is a buff inside obj, and will be freed
1271 * when it is freed.
1272 */
1273 MEM(p = json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN));
1274 MEM(out = talloc_typed_strdup(ctx, p));
1275
1276 /*
1277 * Free the JSON structure, it's not needed any more
1278 */
1280
1281 return out;
1282}
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:381
#define NUM_ELEMENTS(_t)
Definition build.h:337
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#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:268
#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:297
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
#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:139
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition debug.h:216
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
fr_dict_enum_value_t * 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:3349
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:231
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3395
ssize_t fr_dict_valid_name(char const *name, ssize_t len)
Definition dict_util.c:4620
char const * name
Enum name.
Definition dict.h:228
#define FR_DICT_ATTR_MAX_NAME_LEN
Maximum length of a attribute name.
Definition dict.h:475
Value of an enumerated attribute.
Definition dict.h:227
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:811
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:1239
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:1095
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:605
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:486
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:459
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:950
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:644
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:1157
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:559
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:532
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_MAX
Number of defined data types.
@ 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_VALUE_BOX
A boxed value.
@ 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_VOID
User data.
@ 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:3158
#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:1454
#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:445
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:70
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:43
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
#define FR_TYPE_STRUCTURAL
Definition types.h:296
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:433
#define FR_TYPE_LEAF
Definition types.h:297
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:5352
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:3352
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:3740
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:3723
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:4148
static fr_slen_t data
Definition value.h:1265
#define FR_VALUE_BOX_INITIALISER_NULL(_vb)
A static initialiser for stack/globally allocated boxes.
Definition value.h:488
#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:871
int format(printf, 5, 0))
static size_t char ** out
Definition value.h:997