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