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: a39358dfc2afafc366995fcb8e106d4f71c63d96 $")
24
25#include <freeradius-devel/util/dict_priv.h>
26#include <freeradius-devel/util/print.h>
27#include <freeradius-devel/util/proto.h>
28#include <ctype.h>
29
31{
32 fr_sbuff_t our_out = FR_SBUFF(out);
33
34#define FLAG_SET(_flag) if (flags->_flag) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, STRINGIFY(_flag)",")
35
36 FLAG_SET(is_root);
37 FLAG_SET(is_unknown);
38 FLAG_SET(is_raw);
39 FLAG_SET(internal);
40 FLAG_SET(array);
41 FLAG_SET(has_value);
42 FLAG_SET(counter);
43 FLAG_SET(name_only);
44
45 if (dict && !flags->extra && flags->subtype) {
46 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", flags->subtype);
47 FR_SBUFF_IN_CHAR_RETURN(&our_out, ',');
48 }
49
50 if (flags->length) {
51 switch (type) {
53 /*
54 * Bit fields are in the dicts as various
55 * `uint*` types. But with special flags
56 * saying they're bit fields.
57 */
58 if (flags->extra && (flags->subtype == FLAG_BIT_FIELD)) {
59 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "bit[%u],", flags->length);
60 }
61 break;
62
63 default:
64 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "length=%i,", flags->length);
65 break;
66 }
67 }
68 if (flags->extra) {
69 switch (flags->subtype) {
70 case FLAG_KEY_FIELD:
71 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "key,");
72 break;
73
74 case FLAG_BIT_FIELD:
75 break;
76
78 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "length=uint8,");
79 break;
80
82 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "length=uint16,");
83 break;
84
85 default:
86 break;
87 }
88 }
89
90 /*
91 * Print out the date precision.
92 */
93 if ((type == FR_TYPE_DATE) || (type == FR_TYPE_TIME_DELTA)) {
95 fr_table_str_by_value(fr_time_precision_table, flags->flag_time_res, "?"));
96 FR_SBUFF_IN_CHAR_RETURN(&our_out, ',');
97 if (flags->is_unsigned) FR_SBUFF_IN_CHAR_RETURN(&our_out, 'u');
98 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "int%d", flags->length << 3);
99 }
100
101 /*
102 * Remove trailing commas.
103 */
104 fr_sbuff_trim(&our_out, (bool[UINT8_MAX + 1]){ [','] = true });
105
106 /*
107 * Ensure that the buffer is initialized.
108 */
109 if (fr_sbuff_used(&our_out) == 0) FR_SBUFF_IN_CHAR_RETURN(&our_out, '\0');
110
111 FR_SBUFF_SET_RETURN(out, &our_out);
112}
113
114/** Build the da_stack for the specified DA and encode the path by name in OID form
115 *
116 * @param[out] out Where to write the OID.
117 * @param[in] ancestor If not NULL, only print OID portion between ancestor and da.
118 * @param[in] da to print OID string for.
119 * @param[in] numeric print the OID components as numbers, not attribute names.
120 * @return
121 * - >0 The number of bytes written to the buffer.
122 * - <= 0 The number of bytes we would have needed to write the
123 * next OID component.
124 */
126 fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric)
127{
128 int i;
129 int depth = 0;
130 fr_da_stack_t da_stack;
131 fr_sbuff_t our_out = FR_SBUFF(out);
132
133 /*
134 * If the ancestor and the DA match, there's
135 * no OID string to print.
136 */
137 if ((ancestor == da) || (da->depth == 0)) return 0;
138
139 fr_proto_da_stack_build(&da_stack, da);
140
141 /*
142 * We may have swapped from a known to an unknown
143 * attribute. We still print out the unknown one.
144 */
145 if (ancestor && da->flags.is_unknown) {
146 fr_assert(da->depth > ancestor->depth);
147
148 ancestor = da_stack.da[ancestor->depth - 1];
149 }
150
151 if (ancestor) {
152 if (da_stack.da[ancestor->depth - 1] != ancestor) {
153 fr_strerror_printf("Attribute '%s' is not a descendent of \"%s\"", da->name, ancestor->name);
154 return 0;
155 }
156 depth = ancestor->depth;
157 }
158
159 /*
160 * We don't print the ancestor, we print the OID
161 * between it and the da.
162 */
163 if (numeric) {
164 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", da_stack.da[depth]->attr);
165 for (i = depth + 1; i < (int)da->depth; i++) {
166 FR_SBUFF_IN_CHAR_RETURN(&our_out, '.');
167 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", da_stack.da[i]->attr);
168 }
169 } else {
170 FR_SBUFF_IN_STRCPY_RETURN(&our_out, da_stack.da[depth]->name);
171 for (i = depth + 1; i < (int)da->depth; i++) {
172 FR_SBUFF_IN_CHAR_RETURN(&our_out, '.');
173 FR_SBUFF_IN_STRCPY_RETURN(&our_out, da_stack.da[i]->name);
174 }
175 }
176 FR_SBUFF_SET_RETURN(out, &our_out);
177}
178
179typedef struct {
180 FILE *fp;
182 char prefix[256];
183 char flags[256];
184 char oid[256];
185 unsigned int start_depth;
187
188static int dict_attr_debug(fr_dict_attr_t const *da, void *uctx)
189{
190 fr_dict_attr_debug_t *ctx = uctx;
191 fr_hash_iter_t iter;
192 fr_dict_enum_value_t const *enumv;
194
196 ctx->dict, da->type, &da->flags);
197
198 snprintf(ctx->prefix, sizeof(ctx->prefix),
199 "[%02u] 0x%016" PRIxPTR "%*s",
200 da->depth,
201 (unsigned long)da,
202 (da->depth - ctx->start_depth) * 4, "");
203
204 fprintf(ctx->fp, "%s%s(%u) %s %s\n",
205 ctx->prefix,
206 da->name,
207 da->attr,
208 fr_type_to_str(da->type),
209 ctx->flags);
210
211 dict_attr_ext_debug(ctx->prefix, da); /* Print all the extension debug info */
212
214 if (!ext || !ext->name_by_value) return 0;
215
216 for (enumv = fr_hash_table_iter_init(ext->name_by_value, &iter);
217 enumv;
218 enumv = fr_hash_table_iter_next(ext->name_by_value, &iter)) {
219 char *value = fr_asprintf(NULL, "%pV", enumv->value);
220
221 fprintf(ctx->fp, "%s %s -> %s\n",
222 ctx->prefix,
223 enumv->name,
224 value);
226 }
227
228 return 0;
229}
230
232{
233 fr_dict_attr_debug_t uctx = {
234 .fp = fp,
235 .dict = fr_dict_by_da(da),
236 .start_depth = da->depth,
237 };
238 fr_hash_table_t *namespace;
239 fr_hash_iter_t iter;
240 fr_dict_attr_t *our_da;
241
242 namespace = dict_attr_namespace(da);
243 if (!namespace) {
244 fprintf(fp, "%s does not have namespace\n", da->name);
245 return;
246 }
247
248 for (our_da = fr_hash_table_iter_init(namespace, &iter);
249 our_da;
250 our_da = fr_hash_table_iter_next(namespace, &iter)) {
251 dict_attr_debug(our_da, &uctx);
252 }
253}
254
255void fr_dict_attr_debug(FILE *fp, fr_dict_attr_t const *da)
256{
257 fr_dict_attr_debug_t uctx = {
258 .fp = fp,
259 .dict = fr_dict_by_da(da),
260 .start_depth = da->depth,
261 };
262
263 dict_attr_debug(da, &uctx);
264 (void)fr_dict_walk(da, dict_attr_debug, &uctx);
265}
266
267void fr_dict_debug(FILE *fp, fr_dict_t const *dict)
268{
270}
271
272static int dict_attr_export(fr_dict_attr_t const *da, void *uctx)
273{
274 fr_dict_attr_debug_t *ctx = uctx;
275
276 (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(ctx->prefix, sizeof(ctx->prefix)),
277 NULL, da, false);
278 (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(ctx->oid, sizeof(ctx->oid)),
279 NULL, da, true);
280
281 *ctx->flags = 0; /* some attributes don't have flags */
283 ctx->dict, da->type, &da->flags);
284 fprintf(ctx->fp, "ATTRIBUTE\t%-40s\t%-20s\t%s\t%s\n",
285 ctx->prefix,
286 ctx->oid,
287 fr_type_to_str(da->type),
288 ctx->flags);
289
290 return 0;
291}
292
293static void fr_dict_attr_export(FILE *fp, fr_dict_attr_t const *da)
294{
295 fr_dict_attr_debug_t uctx = {
296 .fp = fp,
297 .dict = fr_dict_by_da(da),
298 .start_depth = da->depth
299 };
300
301 dict_attr_export(da, &uctx);
302 (void)fr_dict_walk(da, dict_attr_export, &uctx);
303}
304
305/** Export in the standard form: ATTRIBUTE name oid flags
306 *
307 */
308void fr_dict_export(FILE *fp, fr_dict_t const *dict)
309{
311}
312
314{
315 fr_hash_table_t *namespace;
316 fr_hash_iter_t iter;
317 fr_dict_attr_t *da;
318 char buffer [256];
319
320 namespace = dict_attr_namespace(parent);
321 if (!namespace) {
322 fprintf(fp, "%s does not have namespace\n", parent->name);
323 return;
324 }
325
326 for (da = fr_hash_table_iter_init(namespace, &iter);
327 da;
328 da = fr_hash_table_iter_next(namespace, &iter)) {
329 fr_dict_attr_t const *ref;
330
331 if (!da->flags.is_alias) continue;
332
333 if (!fr_type_is_leaf(da->type)) continue;
334
335 ref = fr_dict_attr_ref(da);
336 if (!ref) continue;
337
338 if (da->depth == ref->depth) continue;
339
340#ifdef STATIC_ANALYZER
341 buffer[0] = '\0';
342#endif
343
345 NULL, ref, false);
346
347 fprintf(fp, "%-40s\t%s\n", da->name, buffer);
348 }
349}
350
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:2613
int fr_dict_walk(fr_dict_attr_t const *da, fr_dict_walk_t callback, void *uctx)
Definition dict_util.c:4784
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2407
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
@ 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
uint8_t subtype
protocol-specific values, OR key fields
Definition dict.h:126
uint8_t length
length of the attribute
Definition dict.h:132
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:181
void fr_dict_namespace_debug(FILE *fp, fr_dict_attr_t const *da)
Definition dict_print.c:231
static int dict_attr_export(fr_dict_attr_t const *da, void *uctx)
Definition dict_print.c:272
void fr_dict_alias_export(FILE *fp, fr_dict_attr_t const *parent)
Definition dict_print.c:313
void fr_dict_debug(FILE *fp, fr_dict_t const *dict)
Definition dict_print.c:267
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:30
static void fr_dict_attr_export(FILE *fp, fr_dict_attr_t const *da)
Definition dict_print.c:293
void fr_dict_attr_debug(FILE *fp, fr_dict_attr_t const *da)
Definition dict_print.c:255
unsigned int start_depth
Definition dict_print.c:185
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:125
#define FLAG_SET(_flag)
static int dict_attr_debug(fr_dict_attr_t const *da, void *uctx)
Definition dict_print.c:188
void fr_dict_export(FILE *fp, fr_dict_t const *dict)
Export in the standard form: ATTRIBUTE name oid flags.
Definition dict_print.c:308
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:2128
#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