The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
dict_print.c
Go to the documentation of this file.
1/*
2 * This program 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
5 * (at 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/** Print dictionary attributes, flags, etc...
18 *
19 * @file src/lib/util/dict_print.c
20 *
21 * @copyright 2019 The FreeRADIUS server project
22 */
23RCSID("$Id: 0466947d99253a9430b60216a96f90dcc1ef0b40 $")
24
25#include <freeradius-devel/util/dict_priv.h>
26#include <freeradius-devel/util/print.h>
27#include <freeradius-devel/util/proto.h>
28
30{
31 fr_sbuff_t our_out = FR_SBUFF(out);
32
33#define FLAG_SET(_flag) if (flags->_flag) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, STRINGIFY(_flag)",")
34
35 FLAG_SET(is_root);
36 FLAG_SET(is_unknown);
37 FLAG_SET(is_raw);
38 FLAG_SET(internal);
39 FLAG_SET(array);
40 FLAG_SET(has_value);
41 FLAG_SET(counter);
42 FLAG_SET(name_only);
43
44 if (dict && !flags->extra && flags->subtype) {
45 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", flags->subtype);
46 FR_SBUFF_IN_CHAR_RETURN(&our_out, ',');
47 }
48
49 if (flags->length) {
50 switch (type) {
52 /*
53 * Bit fields are in the dicts as various
54 * `uint*` types. But with special flags
55 * saying they're bit fields.
56 */
57 if (flags->extra && (flags->subtype == FLAG_BIT_FIELD)) {
58 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "bit[%u],", flags->length);
59 }
60 break;
61
62 default:
63 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "length=%i,", flags->length);
64 break;
65 }
66 }
67 if (flags->extra) {
68 switch (flags->subtype) {
69 case FLAG_KEY_FIELD:
70 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "key,");
71 break;
72
73 case FLAG_BIT_FIELD:
74 break;
75
77 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "length=uint8,");
78 break;
79
81 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "length=uint16,");
82 break;
83
84 default:
85 break;
86 }
87 }
88
89 /*
90 * Print out the date precision.
91 */
92 if ((type == FR_TYPE_DATE) || (type == FR_TYPE_TIME_DELTA)) {
94 fr_table_str_by_value(fr_time_precision_table, flags->flag_time_res, "?"));
95 FR_SBUFF_IN_CHAR_RETURN(&our_out, ',');
96 if (flags->is_unsigned) FR_SBUFF_IN_CHAR_RETURN(&our_out, 'u');
97 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "int%d", flags->length << 3);
98 }
99
100 /*
101 * Remove trailing commas.
102 */
103 fr_sbuff_trim(&our_out, (bool[UINT8_MAX + 1]){ [','] = true });
104
105 /*
106 * Ensure that the buffer is initialized.
107 */
108 if (fr_sbuff_used(&our_out) == 0) FR_SBUFF_IN_CHAR_RETURN(&our_out, '\0');
109
110 FR_SBUFF_SET_RETURN(out, &our_out);
111}
112
113/** Build the da_stack for the specified DA and encode the path by name in OID form
114 *
115 * @param[out] out Where to write the OID.
116 * @param[in] ancestor If not NULL, only print OID portion between ancestor and da.
117 * @param[in] da to print OID string for.
118 * @param[in] numeric print the OID components as numbers, not attribute names.
119 * @return
120 * - >0 The number of bytes written to the buffer.
121 * - <= 0 The number of bytes we would have needed to write the
122 * next OID component.
123 */
125 fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric)
126{
127 int i;
128 int depth = 0;
129 fr_da_stack_t da_stack;
130 fr_sbuff_t our_out = FR_SBUFF(out);
131
132 /*
133 * If the ancestor and the DA match, there's
134 * no OID string to print.
135 */
136 if ((ancestor == da) || (da->depth == 0)) return 0;
137
138 fr_proto_da_stack_build(&da_stack, da);
139
140 /*
141 * We may have swapped from a known to an unknown
142 * attribute. We still print out the unknown one.
143 */
144 if (ancestor && da->flags.is_unknown) {
145 fr_assert(da->depth > ancestor->depth);
146
147 ancestor = da_stack.da[ancestor->depth - 1];
148 }
149
150 if (ancestor) {
151 if (da_stack.da[ancestor->depth - 1] != ancestor) {
152 fr_strerror_printf("Attribute '%s' is not a descendent of \"%s\"", da->name, ancestor->name);
153 return 0;
154 }
155 depth = ancestor->depth;
156 }
157
158 /*
159 * We don't print the ancestor, we print the OID
160 * between it and the da.
161 */
162 if (numeric) {
163 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", da_stack.da[depth]->attr);
164 for (i = depth + 1; i < (int)da->depth; i++) {
165 FR_SBUFF_IN_CHAR_RETURN(&our_out, '.');
166 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", da_stack.da[i]->attr);
167 }
168 } else {
169 FR_SBUFF_IN_STRCPY_RETURN(&our_out, da_stack.da[depth]->name);
170 for (i = depth + 1; i < (int)da->depth; i++) {
171 FR_SBUFF_IN_CHAR_RETURN(&our_out, '.');
172 FR_SBUFF_IN_STRCPY_RETURN(&our_out, da_stack.da[i]->name);
173 }
174 }
175 FR_SBUFF_SET_RETURN(out, &our_out);
176}
177
178typedef struct {
179 FILE *fp;
181 char prefix[256];
182 char flags[256];
183 char oid[256];
184 unsigned int start_depth;
186
187static int dict_attr_debug(fr_dict_attr_t const *da, void *uctx)
188{
189 fr_dict_attr_debug_t *ctx = uctx;
190 fr_hash_iter_t iter;
191 fr_dict_enum_value_t const *enumv;
193
195 ctx->dict, da->type, &da->flags);
196
197 snprintf(ctx->prefix, sizeof(ctx->prefix),
198 "[%02u] 0x%016" PRIxPTR "%*s",
199 da->depth,
200 (unsigned long)da,
201 (da->depth - ctx->start_depth) * 4, "");
202
203 fprintf(ctx->fp, "%s%s(%u) %s %s\n",
204 ctx->prefix,
205 da->name,
206 da->attr,
207 fr_type_to_str(da->type),
208 ctx->flags);
209
210 dict_attr_ext_debug(ctx->prefix, da); /* Print all the extension debug info */
211
213 if (!ext || !ext->name_by_value) return 0;
214
215 for (enumv = fr_hash_table_iter_init(ext->name_by_value, &iter);
216 enumv;
217 enumv = fr_hash_table_iter_next(ext->name_by_value, &iter)) {
218 char *value = fr_asprintf(NULL, "%pV", enumv->value);
219
220 fprintf(ctx->fp, "%s %s -> %s\n",
221 ctx->prefix,
222 enumv->name,
223 value);
225 }
226
227 return 0;
228}
229
231{
232 fr_dict_attr_debug_t uctx = {
233 .fp = fp,
234 .dict = fr_dict_by_da(da),
235 .start_depth = da->depth,
236 };
237 fr_hash_table_t *namespace;
238 fr_hash_iter_t iter;
239 fr_dict_attr_t *our_da;
240
241 namespace = dict_attr_namespace(da);
242 if (!namespace) {
243 fprintf(fp, "%s does not have namespace\n", da->name);
244 return;
245 }
246
247 for (our_da = fr_hash_table_iter_init(namespace, &iter);
248 our_da;
249 our_da = fr_hash_table_iter_next(namespace, &iter)) {
250 dict_attr_debug(our_da, &uctx);
251 }
252}
253
254void fr_dict_attr_debug(FILE *fp, fr_dict_attr_t const *da)
255{
256 fr_dict_attr_debug_t uctx = {
257 .fp = fp,
258 .dict = fr_dict_by_da(da),
259 .start_depth = da->depth,
260 };
261
262 dict_attr_debug(da, &uctx);
263 (void)fr_dict_walk(da, dict_attr_debug, &uctx);
264}
265
266void fr_dict_debug(FILE *fp, fr_dict_t const *dict)
267{
269}
270
271static int dict_attr_export(fr_dict_attr_t const *da, void *uctx)
272{
273 fr_dict_attr_debug_t *ctx = uctx;
274
275 (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(ctx->prefix, sizeof(ctx->prefix)),
276 NULL, da, false);
277 (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(ctx->oid, sizeof(ctx->oid)),
278 NULL, da, true);
279
280 *ctx->flags = 0; /* some attributes don't have flags */
282 ctx->dict, da->type, &da->flags);
283 fprintf(ctx->fp, "ATTRIBUTE\t%-40s\t%-20s\t%s\t%s\n",
284 ctx->prefix,
285 ctx->oid,
286 fr_type_to_str(da->type),
287 ctx->flags);
288
289 return 0;
290}
291
292static void fr_dict_attr_export(FILE *fp, fr_dict_attr_t const *da)
293{
294 fr_dict_attr_debug_t uctx = {
295 .fp = fp,
296 .dict = fr_dict_by_da(da),
297 .start_depth = da->depth
298 };
299
300 dict_attr_export(da, &uctx);
301 (void)fr_dict_walk(da, dict_attr_export, &uctx);
302}
303
304/** Export in the standard form: ATTRIBUTE name oid flags
305 *
306 */
307void fr_dict_export(FILE *fp, fr_dict_t const *dict)
308{
310}
311
313{
314 fr_hash_table_t *namespace;
315 fr_hash_iter_t iter;
316 fr_dict_attr_t *da;
317 char buffer [256];
318
319 namespace = dict_attr_namespace(parent);
320 if (!namespace) {
321 fprintf(fp, "%s does not have namespace\n", parent->name);
322 return;
323 }
324
325 for (da = fr_hash_table_iter_init(namespace, &iter);
326 da;
327 da = fr_hash_table_iter_next(namespace, &iter)) {
328 fr_dict_attr_t const *ref;
329
330 if (!da->flags.is_alias) continue;
331
332 if (!fr_type_is_leaf(da->type)) continue;
333
334 ref = fr_dict_attr_ref(da);
335 if (!ref) continue;
336
337 if (da->depth == ref->depth) continue;
338
339#ifdef STATIC_ANALYZER
340 buffer[0] = '\0';
341#endif
342
344 NULL, ref, false);
345
346 fprintf(fp, "%-40s\t%s\n", da->name, buffer);
347 }
348}
349
static int const char char buffer[256]
Definition acutest.h:576
#define RCSID(id)
Definition build.h:485
fr_dict_t const * fr_dict_by_da(fr_dict_attr_t const *da)
Attempt to locate the protocol dictionary containing an attribute.
Definition dict_util.c:2608
int fr_dict_walk(fr_dict_attr_t const *da, fr_dict_walk_t callback, void *uctx)
Definition dict_util.c:4779
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2402
unsigned int extra
really "subtype is used by dict, not by protocol"
Definition dict.h:115
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:235
@ FR_DICT_ATTR_EXT_ENUMV
Enumeration values.
Definition dict.h:173
unsigned int is_unsigned
hackity hack for dates and time deltas
Definition dict.h:95
char const * name
Enum name.
Definition dict.h:232
uint8_t subtype
protocol-specific values, OR key fields
Definition dict.h:126
uint8_t length
length of the attribute
Definition dict.h:132
@ FLAG_LENGTH_UINT8
string / octets type is prefixed by uint8 of length
Definition dict.h:153
@ FLAG_LENGTH_UINT16
string / octets type is prefixed by uint16 of length
Definition dict.h:154
@ FLAG_KEY_FIELD
this is a key field for a subsequent struct
Definition dict.h:151
@ FLAG_BIT_FIELD
bit field inside of a struct
Definition dict.h:152
Values of the encryption flags.
Value of an enumerated attribute.
Definition dict.h:231
fr_hash_table_t * name_by_value
Lookup a name by value.
Definition dict_ext.h:110
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition dict_ext.h:140
static fr_dict_attr_t const * fr_dict_attr_ref(fr_dict_attr_t const *da)
Return the reference associated with a group type attribute.
Definition dict_ext.h:184
Attribute extension - Holds enumeration values.
Definition dict_ext.h:107
static void dict_attr_ext_debug(char const *name, fr_dict_attr_t const *da)
Print extension debug information for attributes.
fr_dict_t const * dict
Definition dict_print.c:180
void fr_dict_namespace_debug(FILE *fp, fr_dict_attr_t const *da)
Definition dict_print.c:230
static int dict_attr_export(fr_dict_attr_t const *da, void *uctx)
Definition dict_print.c:271
void fr_dict_alias_export(FILE *fp, fr_dict_attr_t const *parent)
Definition dict_print.c:312
void fr_dict_debug(FILE *fp, fr_dict_t const *dict)
Definition dict_print.c:266
ssize_t fr_dict_attr_flags_print(fr_sbuff_t *out, fr_dict_t const *dict, fr_type_t type, fr_dict_attr_flags_t const *flags)
Definition dict_print.c:29
static void fr_dict_attr_export(FILE *fp, fr_dict_attr_t const *da)
Definition dict_print.c:292
void fr_dict_attr_debug(FILE *fp, fr_dict_attr_t const *da)
Definition dict_print.c:254
unsigned int start_depth
Definition dict_print.c:184
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)
Build the da_stack for the specified DA and encode the path by name in OID form.
Definition dict_print.c:124
#define FLAG_SET(_flag)
static int dict_attr_debug(fr_dict_attr_t const *da, void *uctx)
Definition dict_print.c:187
void fr_dict_export(FILE *fp, fr_dict_t const *dict)
Export in the standard form: ATTRIBUTE name oid flags.
Definition dict_print.c:307
Test enumeration values.
Definition dict_test.h:92
void * fr_hash_table_iter_next(fr_hash_table_t *ht, fr_hash_iter_t *iter)
Iterate over entries in a hash table.
Definition hash.c:626
void * fr_hash_table_iter_init(fr_hash_table_t *ht, fr_hash_iter_t *iter)
Initialise an iterator.
Definition hash.c:678
Stores the state of the current iteration operation.
Definition hash.h:41
talloc_free(reap)
fr_type_t
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
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)
#define UINT8_MAX
static uint8_t depth(fr_minmax_heap_index_t i)
Definition minmax_heap.c:83
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition print.c:874
void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da)
Build a complete DA stack from the da back to the root.
Definition proto.c:118
#define fr_assert(_expr)
Definition rad_assert.h:38
size_t fr_sbuff_trim(fr_sbuff_t *sbuff, bool const to_trim[static UINT8_MAX+1])
Trim trailing characters from a string we're composing.
Definition sbuff.c:2130
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#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_OUT(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
fr_aka_sim_id_type_t type
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
fr_table_num_ordered_t const fr_time_precision_table[]
Definition time.c:46
static fr_slen_t parent
Definition pair.h:845
fr_dict_attr_t const * da[FR_DICT_MAX_TLV_STACK+1]
The stack.
Definition proto.h:56
Structure for holding the stack of dictionary attributes being encoded.
Definition proto.h:54
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_type_is_leaf(_x)
Definition types.h:372
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_FIXED_SIZE
Definition types.h:290
static size_t char ** out
Definition value.h:1012