The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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 
52  { FR_CONF_OFFSET("prefix", fr_json_format_attr_t, prefix) },
54 };
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 
71 static inline CC_HINT(always_inline)
72 void 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  */
96 int 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 *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 *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 
264  case FR_TYPE_STRUCTURAL:
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 
422  case FR_TYPE_IPV4_ADDR:
423  case FR_TYPE_IPV4_PREFIX:
424  case FR_TYPE_IPV6_ADDR:
425  case FR_TYPE_IPV6_PREFIX:
428  case FR_TYPE_IFID:
429  case FR_TYPE_ETHERNET:
430  case FR_TYPE_DATE:
431  case FR_TYPE_TIME_DELTA:
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 
442  case FR_TYPE_STRUCTURAL:
443  fr_strerror_const("Structural boxes not yet supported");
444  return -1;
445 
446  case FR_TYPE_VOID:
447  case FR_TYPE_VALUE_BOX:
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  */
486 static int json_afrom_value_box(TALLOC_CTX *ctx, json_object **out,
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 
511  MEM(obj = json_object_from_value_box(vb));
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  */
560 {
561  bool ret = true;
562 
563  fr_assert(format);
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 \
606 do { \
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  */
644 static 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 */
652  fr_assert(format);
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  */
699  case FR_TYPE_STRUCTURAL:
700  value = json_object_afrom_pair_list(ctx, &vp->vp_group, format);
701  break;
702 
703  default:
704  INVALID_TYPE;
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  */
811 static 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 */
820  fr_assert(format);
821  fr_assert(format->output_mode == JSON_MODE_OBJECT_SIMPLE);
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  */
868  case FR_TYPE_STRUCTURAL:
869  value = json_smplobj_afrom_pair_list(ctx, &vp->vp_group, format);
870  break;
871 
872  default:
873  INVALID_TYPE;
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  */
950 static 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 */
959  fr_assert(format);
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:
1005  INVALID_TYPE;
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  */
1095 static 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 */
1102  fr_assert(format);
1103  fr_assert(format->output_mode == JSON_MODE_ARRAY_OF_VALUES);
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:
1132  INVALID_TYPE;
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  */
1157 static 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 */
1165  fr_assert(format);
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:
1197  INVALID_TYPE;
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  */
1239 char *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;
1259  MEM(obj = json_value_array_afrom_pair_list(ctx, vps, format));
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:574
#define fr_base16_encode(_out, _in)
Definition: base16.h:57
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define unlikely(_x)
Definition: build.h:379
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:627
#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:564
#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 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:230
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:227
#define FR_DICT_ATTR_MAX_NAME_LEN
Maximum length of a attribute name.
Definition: dict.h:472
Value of an enumerated attribute.
Definition: dict.h:226
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
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 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
size_t fr_json_format_table_len
Definition: json.c:43
static conf_parser_t const json_format_value_config[]
Definition: json.c:56
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 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 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_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
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
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
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
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
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
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
Definition: merged_model.c:113
@ FR_TYPE_FLOAT32
Single precision floating point.
Definition: merged_model.c:108
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
Definition: merged_model.c:86
@ FR_TYPE_INT8
8 Bit signed integer.
Definition: merged_model.c:103
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
Definition: merged_model.c:93
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
Definition: merged_model.c:89
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_MAX
Number of defined data types.
Definition: merged_model.c:130
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_INT64
64 Bit signed integer.
Definition: merged_model.c:106
@ FR_TYPE_INT16
16 Bit signed integer.
Definition: merged_model.c:104
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
Definition: merged_model.c:111
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
Definition: merged_model.c:92
@ FR_TYPE_VALUE_BOX
A boxed value.
Definition: merged_model.c:125
@ FR_TYPE_UINT8
8 Bit unsigned integer.
Definition: merged_model.c:97
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_INT32
32 Bit signed integer.
Definition: merged_model.c:105
@ FR_TYPE_UINT64
64 Bit unsigned integer.
Definition: merged_model.c:100
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
Definition: merged_model.c:88
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
Definition: merged_model.c:87
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
@ FR_TYPE_BOOL
A truth value.
Definition: merged_model.c:95
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
Definition: merged_model.c:115
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
Definition: merged_model.c:91
@ FR_TYPE_IFID
Interface ID.
Definition: merged_model.c:90
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
@ FR_TYPE_FLOAT64
Double precision floating point.
Definition: merged_model.c:109
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
ssize_t fr_slen_t
Definition: merged_model.c:35
#define UINT8_MAX
Definition: merged_model.c:32
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 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:1432
#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_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_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition: pair_inline.c:43
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
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
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_STRUCTURAL
Definition: types.h:296
#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
FR_SBUFF_SET_RETURN(sbuff, &our_sbuff)
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