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 && (parent->type == FR_TYPE_GROUP)) { \
24 parent = fr_dict_attr_ref(parent); \
25 if (parent->flags.is_root) parent = NULL; \
26 } \
27 if (parent && (parent == vp->da)) parent = NULL; \
28 } while (0)
29
30/** Pair serialisation API
31 *
32 * @file src/lib/util/pair_print.c
33 *
34 * @copyright 2020 The FreeRADIUS server project
35 */
36#include <freeradius-devel/util/pair.h>
37#include <freeradius-devel/util/talloc.h>
38#include <freeradius-devel/util/proto.h>
39#include <freeradius-devel/util/pair_legacy.h>
40
41/** Print the value of an attribute to a string
42 *
43 * @param[in] out Where to write the string.
44 * @param[in] vp to print.
45 * @param[in] quote Char to add before and after printed value,
46 * if 0 no char will be added, if < 0 raw string
47 * will be added.
48 * @return
49 * - >= 0 length of data written to out.
50 * - <0 the number of bytes we would have needed to write
51 * the complete string to out.
52 */
54{
55 fr_sbuff_t our_out;
56 ssize_t slen;
57
59
60 our_out = FR_SBUFF(out);
61
62 switch (vp->vp_type) {
63 /*
64 * For structural types descend down
65 */
67 if (fr_pair_list_empty(&vp->vp_group)) {
68 FR_SBUFF_IN_CHAR_RETURN(&our_out, '{', ' ', '}');
69
70 } else {
71 FR_SBUFF_IN_CHAR_RETURN(&our_out, '{', ' ');
72
73 FR_SBUFF_RETURN(fr_pair_list_print, &our_out, vp->da, &vp->vp_group);
74
75 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ', '}');
76 }
77
78 FR_SBUFF_SET_RETURN(out, &our_out);
79
80 /*
81 * For simple types just print the box
82 */
83 default:
84 /*
85 * If it's raw / unknown and not octets, print the cast before the type.
86 *
87 * Otherwise on parsing, we don't know how to interpret the value. :(
88 */
89 if ((vp->da->flags.is_raw || vp->da->flags.is_unknown) &&
90 (vp->vp_type != FR_TYPE_OCTETS)) {
91 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "(%s) ", fr_type_to_str(vp->vp_type));
92 }
93
94 slen = fr_value_box_print_quoted(&our_out, &vp->data, quote);
95 if (slen <= 0) return slen;
96 }
97
98 FR_SBUFF_SET_RETURN(out, &our_out);
99}
100
101/** Print one attribute and value to a string
102 *
103 * Print a fr_pair_t in the format:
104@verbatim
105 <attribute_name> <op> <value>
106@endverbatim
107 * to a string.
108 *
109 * @param[in] out Where to write the string.
110 * @param[in] parent If not NULL, only print OID components from
111 * this parent to the VP.
112 * @param[in] vp to print.
113 * @return
114 * - Length of data written to out.
115 * - value >= outlen on truncation.
116 */
118{
119 char const *token = NULL;
120 fr_sbuff_t our_out = FR_SBUFF(out);
121
123
124 /*
125 * Omit the union if we can.
126 */
127 if ((vp->vp_type == FR_TYPE_UNION) &&
128 (fr_pair_list_num_elements(&vp->vp_group) == 1)) {
129 parent = vp->da;
130 vp = fr_pair_list_head(&vp->vp_group);
131 }
132
133 if ((vp->op > T_INVALID) && (vp->op < T_TOKEN_LAST)) {
134 token = fr_tokens[vp->op];
135 } else {
136 token = "<INVALID-TOKEN>";
137 }
138
140
141 if (vp->vp_raw) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "raw.");
142 FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, parent, vp->da, false);
143 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ');
144 FR_SBUFF_IN_STRCPY_RETURN(&our_out, token);
145 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ');
146
147 if (fr_type_is_leaf(vp->vp_type) && vp->data.enumv && vp->data.enumv->flags.has_value) {
148 char const *name;
149
150 name = fr_dict_enum_name_by_value(vp->data.enumv, &vp->data);
151 if (!name) goto no_enumv;
152
153 FR_SBUFF_IN_CHAR_RETURN(&our_out, ':', ':');
155
156 } else {
157
158 no_enumv:
160 }
161
162 FR_SBUFF_SET_RETURN(out, &our_out);
163}
164
165/** Print one attribute and value to a string with escape rules
166 *
167 * Similar to fr_pair_print(), but secrets are omitted. This function duplicates parts of the functionality
168 * of fr_pair_print(). fr_pair_print_value_quoted(), and fr_value_box_print_quoted(), but for the special
169 * case of secure strings.
170 *
171 * Note that only secrets of type "string" and "octets" are omitted. Other "secret" data types are still
172 * printed as-is.
173 *
174 * "octets" are still printed as "<<< secret >>>". Which won't parse correctly, but that's fine. Because
175 * omitted data is not meant to be parsed into real data.
176 *
177 * @param[in] out Where to write the string.
178 * @param[in] parent If not NULL, only print OID components from
179 * this parent to the VP.
180 * @param[in] vp to print.
181
182 * @return
183 * - < 0 on error
184 * - Length of data written to out.
185 * - value >= outlen on truncation.
186 */
188{
189 char const *token = NULL;
190 fr_sbuff_t our_out = FR_SBUFF(out);
191
193
194 if ((vp->op > T_INVALID) && (vp->op < T_TOKEN_LAST)) {
195 token = fr_tokens[vp->op];
196 } else {
197 token = "<INVALID-TOKEN>";
198 }
199
201
202 if (vp->vp_raw) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "raw.");
203 FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, parent, vp->da, false);
204 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ');
205 FR_SBUFF_IN_STRCPY_RETURN(&our_out, token);
206 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ');
207
208 if (fr_type_is_leaf(vp->vp_type)) {
209 if (!vp->data.secret) {
211
212 } else {
213 switch (vp->vp_type) {
214 case FR_TYPE_STRING:
215 case FR_TYPE_OCTETS:
216 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "<<< secret >>>");
217 break;
218
219 default:
220 fr_assert(0); /* see dict_tokenize.c, which enforces parsing of "secret" in dictionaries */
221 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "<<< secret >>>");
222 break;
223 }
224 }
225 } else {
226 fr_pair_t *child;
227 fr_dcursor_t cursor;
228
230
231 FR_SBUFF_IN_CHAR_RETURN(&our_out, '{', ' ');
232 for (child = fr_pair_dcursor_init(&cursor, &vp->vp_group);
233 child != NULL;
234 child = fr_dcursor_next(&cursor)) {
235 FR_SBUFF_RETURN(fr_pair_print_secure, &our_out, vp->da, child);
236 if (fr_dcursor_next_peek(&cursor)) FR_SBUFF_IN_CHAR_RETURN(&our_out, ',', ' ');
237 }
238 FR_SBUFF_IN_CHAR_RETURN(&our_out, ' ', '}');
239 }
240
241 FR_SBUFF_SET_RETURN(out, &our_out);
242}
243
244/** Print a pair list
245 *
246 * @param[in] out Where to write the string.
247 * @param[in] parent parent da to start from
248 * @param[in] list pair list
249 * @return
250 * - Length of data written to out.
251 * - value >= outlen on truncation.
252 */
254{
255 fr_pair_t *vp;
256 fr_sbuff_t our_out = FR_SBUFF(out);
257
258 vp = fr_pair_list_head(list);
259 if (!vp) {
261 return fr_sbuff_used(out);
262 }
263
265
266 while (true) {
268 vp = fr_pair_list_next(list, vp);
269 if (!vp) break;
270
271 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, ", ");
272 }
273
274 FR_SBUFF_SET_RETURN(out, &our_out);
275}
276
277static 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)
278{
279 fr_dict_attr_t const *parent_da = NULL;
280
281 fr_pair_list_foreach(list, vp) {
283
284 fr_sbuff_set_to_start(sbuff);
285
286 if (vp->vp_raw) (void) fr_sbuff_in_strcpy(sbuff, "raw.");
287
288 if (parent && (parent->vp_type != FR_TYPE_GROUP)) parent_da = parent->da;
289 if (fr_dict_attr_oid_print(sbuff, parent_da, vp->da, false) <= 0) return;
290
291 /*
292 * Recursively print grouped attributes.
293 */
294 switch (vp->vp_type) {
296 fr_log(log, L_DBG, file, line, "%*s%*s {", lvl * 2, "",
297 (int) fr_sbuff_used(sbuff), fr_sbuff_start(sbuff));
298 _fr_pair_list_log(log, lvl + 1, vp, &vp->vp_group, file, line);
299 fr_log(log, L_DBG, file, line, "%*s}", lvl * 2, "");
300 break;
301
302 default:
303 (void) fr_sbuff_in_strcpy(sbuff, " = ");
304 if (fr_value_box_print_quoted(sbuff, &vp->data, T_DOUBLE_QUOTED_STRING)< 0) break;
305
306 fr_log(log, L_DBG, file, line, "%*s%*s", lvl * 2, "",
307 (int) fr_sbuff_used(sbuff), fr_sbuff_start(sbuff));
308 }
309 }
310}
311
312
313/** Print a list of attributes and enumv
314 *
315 * @param[in] log to output to.
316 * @param[in] lvl depth in structural attribute.
317 * @param[in] parent parent attribute
318 * @param[in] list to print.
319 * @param[in] file where the message originated
320 * @param[in] line where the message originated
321 */
322void _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)
323{
324 fr_sbuff_t sbuff;
325 char buffer[1024];
326
327 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
328
329 fr_pair_list_log_sbuff(log, lvl, parent, list, file, line, &sbuff);
330}
331
332static void fr_pair_list_debug_sbuff(FILE *fp, int lvl, fr_pair_t *parent, fr_pair_list_t const *list, fr_sbuff_t *sbuff)
333{
334 fr_dict_attr_t const *parent_da = NULL;
335
336 fr_pair_list_foreach(list, vp) {
338
339 fr_sbuff_set_to_start(sbuff);
340
341 if (vp->vp_raw) (void) fr_sbuff_in_strcpy(sbuff, "raw.");
342
343 if (parent && (parent->vp_type != FR_TYPE_GROUP)) parent_da = parent->da;
344 if (fr_dict_attr_oid_print(sbuff, parent_da, vp->da, false) <= 0) return;
345
346 /*
347 * Recursively print grouped attributes.
348 */
349 switch (vp->vp_type) {
351 fprintf(fp, "%*s%*s {\n", lvl * 2, "", (int) fr_sbuff_used(sbuff), fr_sbuff_start(sbuff));
352 _fr_pair_list_debug(fp, lvl + 1, vp, &vp->vp_group);
353 fprintf(fp, "%*s}\n", lvl * 2, "");
354 break;
355
356 default:
357 (void) fr_sbuff_in_strcpy(sbuff, " = ");
358 if (fr_value_box_print_quoted(sbuff, &vp->data, T_DOUBLE_QUOTED_STRING)< 0) break;
359
360 fprintf(fp, "%*s%*s\n", lvl * 2, "", (int) fr_sbuff_used(sbuff), fr_sbuff_start(sbuff));
361 }
362 }
363}
364
365/** Print a list of attributes and enumv
366 *
367 * @param[in] fp to output to.
368 * @param[in] lvl depth in structural attribute.
369 * @param[in] parent parent attribute
370 * @param[in] list to print.
371 */
372void _fr_pair_list_debug(FILE *fp, int lvl, fr_pair_t *parent, fr_pair_list_t const *list)
373{
374 fr_sbuff_t sbuff;
375 char buffer[1024];
376
377 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
378
379 fr_pair_list_debug_sbuff(fp, lvl, parent, list, &sbuff);
380}
381
382/** Dumps a list to the default logging destination - Useful for calling from debuggers
383 *
384 */
385void fr_pair_list_debug(FILE *fp, fr_pair_list_t const *list)
386{
387 _fr_pair_list_debug(fp, 0, NULL, list);
388}
389
390
391/** Dumps a pair to the default logging destination - Useful for calling from debuggers
392 *
393 */
394void fr_pair_debug(FILE *fp, fr_pair_t const *pair)
395{
396 fr_sbuff_t sbuff;
397 char buffer[1024];
398
399 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
400
401 (void) fr_pair_print(&sbuff, NULL, pair);
402
403 fprintf(fp, "%pV\n", fr_box_strvalue_len(fr_sbuff_start(&sbuff), fr_sbuff_used(&sbuff)));
404}
static int const char char buffer[256]
Definition acutest.h:578
int const char * file
Definition acutest.h:704
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
char const * fr_dict_enum_name_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the name of an enum value in a fr_dict_attr_t.
Definition dict_util.c:3519
#define FR_DICT_ATTR_OID_PRINT_RETURN(...)
Definition dict.h:732
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)
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:372
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:394
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:332
#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:277
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:385
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:322
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:117
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:187
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:53
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:253
#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:193
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:263
#define PAIR_VERIFY_WITH_LIST(_l, _x)
Definition pair.h:194
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:589
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:841
#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:6015
#define fr_box_strvalue_len(_val, _len)
Definition value.h:308
static size_t char ** out
Definition value.h:1023