The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
pair_print.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library 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 GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/*
18 * Groups are printed from the referenced attribute.
19 *
20 * @todo - parent should _never_ be vp->da.
21 */
22#define fr_pair_reset_parent(parent) do { \
23 if (!parent) break; \
24 fr_assert(parent != vp->da); \
25 fr_assert(fr_type_is_structural(parent->type)); \
26 if (parent->type == FR_TYPE_GROUP) { \
27 parent = fr_dict_attr_ref(parent); \
28 if (parent->flags.is_root) { \
29 parent = NULL; \
30 break; \
31 } \
32 } \
33 if (parent->dict != vp->da->dict) parent = NULL; \
34 } while (0)
35
36/** Pair serialisation API
37 *
38 * @file src/lib/util/pair_print.c
39 *
40 * @copyright 2020 The FreeRADIUS server project
41 */
42#include <freeradius-devel/util/pair.h>
43#include <freeradius-devel/util/talloc.h>
44#include <freeradius-devel/util/proto.h>
45#include <freeradius-devel/util/pair_legacy.h>
46
47/** Print the value of an attribute to a string
48 *
49 * @param[in] out Where to write the string.
50 * @param[in] vp to print.
51 * @param[in] quote Char to add before and after printed value,
52 * if 0 no char will be added, if < 0 raw string
53 * will be added.
54 * @return
55 * - >= 0 length of data written to out.
56 * - <0 the number of bytes we would have needed to write
57 * the complete string to out.
58 */
60{
61 fr_sbuff_t our_out;
62 ssize_t slen;
63
65
66 our_out = FR_SBUFF(out);
67
68 switch (vp->vp_type) {
69 /*
70 * For structural types descend down
71 */
73 if (fr_pair_list_empty(&vp->vp_group)) {
74 FR_SBUFF_IN_CHAR_RETURN(&our_out, '{', ' ', '}');
75
76 } else {
77 FR_SBUFF_IN_CHAR_RETURN(&our_out, '{', ' ');
78
79 FR_SBUFF_RETURN(fr_pair_list_print, &our_out, vp->da, &vp->vp_group);
80
81 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ', '}');
82 }
83
84 FR_SBUFF_SET_RETURN(out, &our_out);
85
86 /*
87 * For simple types just print the box
88 */
89 default:
90 /*
91 * If it's raw / unknown and not octets, print the cast before the type.
92 *
93 * Otherwise on parsing, we don't know how to interpret the value. :(
94 */
95 if ((vp->da->flags.is_raw || vp->da->flags.is_unknown) &&
96 (vp->vp_type != FR_TYPE_OCTETS)) {
97 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "(%s) ", fr_type_to_str(vp->vp_type));
98 }
99
100 slen = fr_value_box_print_quoted(&our_out, &vp->data, quote);
101 if (slen <= 0) return slen;
102 }
103
104 FR_SBUFF_SET_RETURN(out, &our_out);
105}
106
107/** Print either a quoted value, an enum, or a normal value.
108 *
109 */
111{
112 fr_sbuff_t our_out = FR_SBUFF(out);
113 char const *name;
114
115 if ((name = fr_value_box_enum_name(&vp->data)) != NULL) {
116 FR_SBUFF_IN_CHAR_RETURN(&our_out, ':', ':');
118 } else {
119
121 }
122
123 FR_SBUFF_SET_RETURN(out, &our_out);
124}
125
126/** Print one attribute and value to a string
127 *
128 * Print a fr_pair_t in the format:
129@verbatim
130 <attribute_name> <op> <value>
131@endverbatim
132 * to a string.
133 *
134 * @param[in] out Where to write the string.
135 * @param[in] parent If not NULL, only print OID components from
136 * this parent to the VP.
137 * @param[in] vp to print.
138 * @return
139 * - Length of data written to out.
140 * - value >= outlen on truncation.
141 */
143{
144 char const *token = NULL;
145 fr_sbuff_t our_out = FR_SBUFF(out);
146
148
149 /*
150 * Omit the union if we can. But if the child is raw, then always print it. That way it's
151 * clearer what's going on.
152 */
153 if (vp->vp_type == FR_TYPE_UNION) {
154 fr_pair_t *child = fr_pair_list_head(&vp->vp_group);
155
156 if (!child->da->flags.is_unknown &&
157 (fr_pair_list_num_elements(&vp->vp_group) == 1)) {
158 parent = vp->da;
159 vp = fr_pair_list_head(&vp->vp_group);
160 }
161 }
162
163 if ((vp->op > T_INVALID) && (vp->op < T_TOKEN_LAST)) {
164 token = fr_tokens[vp->op];
165 } else {
166 token = "<INVALID-TOKEN>";
167 }
168
170
171 if (vp->vp_raw) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "raw.");
172 FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, parent, vp->da, false);
173 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ');
174 FR_SBUFF_IN_STRCPY_RETURN(&our_out, token);
175 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ');
176
178
179 FR_SBUFF_SET_RETURN(out, &our_out);
180}
181
182/** Print one attribute and value to a string with escape rules
183 *
184 * Similar to fr_pair_print(), but secrets are omitted. This function duplicates parts of the functionality
185 * of fr_pair_print(). fr_pair_print_value_quoted(), and fr_value_box_print_quoted(), but for the special
186 * case of secure strings.
187 *
188 * Note that only secrets of type "string" and "octets" are omitted. Other "secret" data types are still
189 * printed as-is.
190 *
191 * "octets" are still printed as "<<< secret >>>". Which won't parse correctly, but that's fine. Because
192 * omitted data is not meant to be parsed into real data.
193 *
194 * @param[in] out Where to write the string.
195 * @param[in] parent If not NULL, only print OID components from
196 * this parent to the VP.
197 * @param[in] vp to print.
198
199 * @return
200 * - < 0 on error
201 * - Length of data written to out.
202 * - value >= outlen on truncation.
203 */
205{
206 char const *token = NULL;
207 fr_sbuff_t our_out = FR_SBUFF(out);
208
210
211 if ((vp->op > T_INVALID) && (vp->op < T_TOKEN_LAST)) {
212 token = fr_tokens[vp->op];
213 } else {
214 token = "<INVALID-TOKEN>";
215 }
216
218
219 if (vp->vp_raw) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "raw.");
220 FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, parent, vp->da, false);
221 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ');
222 FR_SBUFF_IN_STRCPY_RETURN(&our_out, token);
223 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ');
224
225 if (fr_type_is_leaf(vp->vp_type)) {
226 if (!vp->data.secret) {
228
229 } else {
230 switch (vp->vp_type) {
231 case FR_TYPE_STRING:
232 case FR_TYPE_OCTETS:
233 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "<<< secret >>>");
234 break;
235
236 default:
237 fr_assert(0); /* see dict_tokenize.c, which enforces parsing of "secret" in dictionaries */
238 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "<<< secret >>>");
239 break;
240 }
241 }
242 } else {
243 fr_pair_t *child;
244 fr_dcursor_t cursor;
245
247
248 FR_SBUFF_IN_CHAR_RETURN(&our_out, '{', ' ');
249 for (child = fr_pair_dcursor_init(&cursor, &vp->vp_group);
250 child != NULL;
251 child = fr_dcursor_next(&cursor)) {
252 FR_SBUFF_RETURN(fr_pair_print_secure, &our_out, vp->da, child);
253 if (fr_dcursor_next_peek(&cursor)) FR_SBUFF_IN_CHAR_RETURN(&our_out, ',', ' ');
254 }
255 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ', '}');
256 }
257
258 FR_SBUFF_SET_RETURN(out, &our_out);
259}
260
261/** Print a pair list
262 *
263 * @param[in] out Where to write the string.
264 * @param[in] parent parent da to start from
265 * @param[in] list pair list
266 * @return
267 * - Length of data written to out.
268 * - value >= outlen on truncation.
269 */
271{
272 fr_pair_t *vp;
273 fr_sbuff_t our_out = FR_SBUFF(out);
274
275 vp = fr_pair_list_head(list);
276 if (!vp) {
278 return fr_sbuff_used(out);
279 }
280
282
283 while (true) {
285 vp = fr_pair_list_next(list, vp);
286 if (!vp) break;
287
288 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, ", ");
289 }
290
291 FR_SBUFF_SET_RETURN(out, &our_out);
292}
293
294static void fr_pair_list_log_sbuff(fr_log_t const *log, int lvl, fr_pair_t *parent, fr_pair_list_t const *list, char const *file, int line, fr_sbuff_t *sbuff)
295{
296 fr_dict_attr_t const *parent_da = NULL;
297
298 fr_pair_list_foreach(list, vp) {
300
301 fr_sbuff_set_to_start(sbuff);
302
303 if (vp->vp_raw) (void) fr_sbuff_in_strcpy(sbuff, "raw.");
304
305 if (parent && (parent->vp_type != FR_TYPE_GROUP)) parent_da = parent->da;
306 if (fr_dict_attr_oid_print(sbuff, parent_da, vp->da, false) <= 0) return;
307
308 /*
309 * Recursively print grouped attributes.
310 */
311 switch (vp->vp_type) {
313 fr_log(log, L_DBG, file, line, "%*s%*s {", lvl * 2, "",
314 (int) fr_sbuff_used(sbuff), fr_sbuff_start(sbuff));
315 _fr_pair_list_log(log, lvl + 1, vp, &vp->vp_group, file, line);
316 fr_log(log, L_DBG, file, line, "%*s}", lvl * 2, "");
317 break;
318
319 default:
320 (void) fr_sbuff_in_strcpy(sbuff, " = ");
321 if (fr_pair_print_value(sbuff, vp) < 0) break;
322
323 fr_log(log, L_DBG, file, line, "%*s%*s", lvl * 2, "",
324 (int) fr_sbuff_used(sbuff), fr_sbuff_start(sbuff));
325 }
326 }
327}
328
329
330/** Print a list of attributes and enumv
331 *
332 * @param[in] log to output to.
333 * @param[in] lvl depth in structural attribute.
334 * @param[in] parent parent attribute
335 * @param[in] list to print.
336 * @param[in] file where the message originated
337 * @param[in] line where the message originated
338 */
339void _fr_pair_list_log(fr_log_t const *log, int lvl, fr_pair_t *parent, fr_pair_list_t const *list, char const *file, int line)
340{
341 fr_sbuff_t sbuff;
342 char buffer[1024];
343
344 buffer[0] = '\0';
345
346 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
347
348 fr_pair_list_log_sbuff(log, lvl, parent, list, file, line, &sbuff);
349}
350
351static void fr_pair_list_debug_sbuff(FILE *fp, int lvl, fr_pair_t *parent, fr_pair_list_t const *list, fr_sbuff_t *sbuff)
352{
353 fr_dict_attr_t const *parent_da = NULL;
354
355 fr_pair_list_foreach(list, vp) {
357
358 fr_sbuff_set_to_start(sbuff);
359
360 if (vp->vp_raw) (void) fr_sbuff_in_strcpy(sbuff, "raw.");
361
362 if (parent && (parent->vp_type != FR_TYPE_GROUP)) parent_da = parent->da;
363 if (fr_dict_attr_oid_print(sbuff, parent_da, vp->da, false) <= 0) return;
364
365 /*
366 * Recursively print grouped attributes.
367 */
368 switch (vp->vp_type) {
370 fprintf(fp, "%*s%*s {\n", lvl * 2, "", (int) fr_sbuff_used(sbuff), fr_sbuff_start(sbuff));
371 _fr_pair_list_debug(fp, lvl + 1, vp, &vp->vp_group);
372 fprintf(fp, "%*s}\n", lvl * 2, "");
373 break;
374
375 default:
376 (void) fr_sbuff_in_strcpy(sbuff, " = ");
377 if (fr_value_box_print_quoted(sbuff, &vp->data, T_DOUBLE_QUOTED_STRING)< 0) break;
378
379 fprintf(fp, "%*s%*s\n", lvl * 2, "", (int) fr_sbuff_used(sbuff), fr_sbuff_start(sbuff));
380 }
381 }
382}
383
384/** Print a list of attributes and enumv
385 *
386 * @param[in] fp to output to.
387 * @param[in] lvl depth in structural attribute.
388 * @param[in] parent parent attribute
389 * @param[in] list to print.
390 */
391void _fr_pair_list_debug(FILE *fp, int lvl, fr_pair_t *parent, fr_pair_list_t const *list)
392{
393 fr_sbuff_t sbuff;
394 char buffer[1024];
395
396 buffer[0] = '\0';
397
398 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
399
400 fr_pair_list_debug_sbuff(fp, lvl, parent, list, &sbuff);
401}
402
403/** Dumps a list to the default logging destination - Useful for calling from debuggers
404 *
405 */
406void fr_pair_list_debug(FILE *fp, fr_pair_list_t const *list)
407{
408 _fr_pair_list_debug(fp, 0, NULL, list);
409}
410
411
412/** Dumps a pair to the default logging destination - Useful for calling from debuggers
413 *
414 */
415void fr_pair_debug(FILE *fp, fr_pair_t const *pair)
416{
417 fr_sbuff_t sbuff;
418 char buffer[1024];
419
420 buffer[0] = '\0';
421
422 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
423
424 (void) fr_pair_print(&sbuff, NULL, pair);
425
426 fprintf(fp, "%pV\n", fr_box_strvalue_len(fr_sbuff_start(&sbuff), fr_sbuff_used(&sbuff)));
427}
428
429static const char spaces[] = " ";
430
431static void fprintf_pair_list(FILE *fp, fr_pair_list_t const *list, int depth)
432{
433 fr_pair_list_foreach(list, vp) {
434 fprintf(fp, "%.*s", depth, spaces);
435
436 if (fr_type_is_leaf(vp->vp_type)) {
437 fr_fprintf(fp, "%s %s %pV\n", vp->da->name, fr_tokens[vp->op], &vp->data);
438 continue;
439 }
440
442
443 fprintf(fp, "%s = {\n", vp->da->name);
444 fprintf_pair_list(fp, &vp->vp_group, depth + 1);
445 fprintf(fp, "%.*s}\n", depth, spaces);
446 }
447}
448
449void fr_fprintf_pair_list(FILE *fp, fr_pair_list_t const *list)
450{
451 fprintf_pair_list(fp, list, 0);
452}
453
454/*
455 * print.c doesn't include pair.h, and doing so causes too many knock-on effects.
456 */
457void fr_fprintf_pair(FILE *fp, char const *msg, fr_pair_t const *vp)
458{
459 if (msg) fputs(msg, fp);
460
461 if (fr_type_is_leaf(vp->vp_type)) {
462 fr_fprintf(fp, "%s %s %pV\n", vp->da->name, fr_tokens[vp->op], &vp->data);
463 } else {
465
466 fprintf(fp, "%s = {\n", vp->da->name);
467 fprintf_pair_list(fp, &vp->vp_group, 1);
468 fprintf(fp, "}\n");
469 }
470}
static int const char char buffer[256]
Definition acutest.h:578
int const char * file
Definition acutest.h:704
log_entry msg
Definition acutest.h:796
int const char int line
Definition acutest.h:704
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:290
static void * fr_dcursor_next_peek(fr_dcursor_t *cursor)
Return the next iterator item without advancing the cursor.
Definition dcursor.h:305
#define FR_DICT_ATTR_OID_PRINT_RETURN(...)
Definition dict.h:755
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition log.c:577
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:59
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
long int ssize_t
ssize_t fr_dict_attr_oid_print(fr_sbuff_t *out, fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric)
static uint8_t depth(fr_minmax_heap_index_t i)
Definition minmax_heap.c:83
void _fr_pair_list_debug(FILE *fp, int lvl, fr_pair_t *parent, fr_pair_list_t const *list)
Print a list of attributes and enumv.
Definition pair_print.c:391
static void fprintf_pair_list(FILE *fp, fr_pair_list_t const *list, int depth)
Definition pair_print.c:431
void fr_fprintf_pair_list(FILE *fp, fr_pair_list_t const *list)
Definition pair_print.c:449
void fr_pair_debug(FILE *fp, fr_pair_t const *pair)
Dumps a pair to the default logging destination - Useful for calling from debuggers.
Definition pair_print.c:415
static void fr_pair_list_debug_sbuff(FILE *fp, int lvl, fr_pair_t *parent, fr_pair_list_t const *list, fr_sbuff_t *sbuff)
Definition pair_print.c:351
#define fr_pair_reset_parent(parent)
Definition pair_print.c:22
static void fr_pair_list_log_sbuff(fr_log_t const *log, int lvl, fr_pair_t *parent, fr_pair_list_t const *list, char const *file, int line, fr_sbuff_t *sbuff)
Definition pair_print.c:294
void fr_pair_list_debug(FILE *fp, fr_pair_list_t const *list)
Dumps a list to the default logging destination - Useful for calling from debuggers.
Definition pair_print.c:406
void _fr_pair_list_log(fr_log_t const *log, int lvl, fr_pair_t *parent, fr_pair_list_t const *list, char const *file, int line)
Print a list of attributes and enumv.
Definition pair_print.c:339
ssize_t fr_pair_print(fr_sbuff_t *out, fr_dict_attr_t const *parent, fr_pair_t const *vp)
Print one attribute and value to a string.
Definition pair_print.c:142
void fr_fprintf_pair(FILE *fp, char const *msg, fr_pair_t const *vp)
Definition pair_print.c:457
ssize_t fr_pair_print_secure(fr_sbuff_t *out, fr_dict_attr_t const *parent, fr_pair_t const *vp)
Print one attribute and value to a string with escape rules.
Definition pair_print.c:204
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
Definition pair_print.c:59
static const char spaces[]
Definition pair_print.c:429
static ssize_t fr_pair_print_value(fr_sbuff_t *out, fr_pair_t const *vp)
Print either a quoted value, an enum, or a normal value.
Definition pair_print.c:110
ssize_t fr_pair_list_print(fr_sbuff_t *out, fr_dict_attr_t const *parent, fr_pair_list_t const *list)
Print a pair list.
Definition pair_print.c:270
ssize_t fr_fprintf(FILE *fp, char const *fmt,...)
Special version of fprintf which implements custom format specifiers.
Definition print.c:907
#define fr_assert(_expr)
Definition rad_assert.h:38
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:1459
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str)
#define fr_sbuff_init_out(_out, _start, _len_or_end)
#define FR_SBUFF_RETURN(_func, _sbuff,...)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
fr_pair_t * vp
Definition log.h:96
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
char const * fr_tokens[T_TOKEN_LAST]
Definition token.c:79
enum fr_token fr_token_t
@ T_INVALID
Definition token.h:39
@ T_DOUBLE_QUOTED_STRING
Definition token.h:121
#define T_TOKEN_LAST
Definition token.h:129
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
#define PAIR_VERIFY(_x)
Definition pair.h:203
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
#define fr_pair_list_foreach(_list_head, _iter)
Iterate over the contents of a fr_pair_list_t.
Definition pair.h:277
#define PAIR_VERIFY_WITH_LIST(_l, _x)
Definition pair.h:204
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:603
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
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
static fr_slen_t parent
Definition pair.h:855
#define fr_type_is_structural(_x)
Definition types.h:393
@ FR_TYPE_UNION
A union of limited children.
Definition types.h:82
#define FR_TYPE_STRUCTURAL
Definition types.h:317
#define fr_type_is_leaf(_x)
Definition types.h:394
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:455
ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, fr_token_t quote)
Print one boxed value to a string with quotes (where needed)
Definition value.c:6043
#define fr_box_strvalue_len(_val, _len)
Definition value.h:308
static char const * fr_value_box_enum_name(fr_value_box_t const *box)
Decide if we need an enum prefix.
Definition value.h:1133
static size_t char ** out
Definition value.h:1023