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: b8e207f524e1e272de12adcfe7e2a3b3f874973a $")
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 if (ancestor && (ancestor->flags.is_root)) ancestor = NULL;
139
140 fr_proto_da_stack_build(&da_stack, da);
141
142 /*
143 * We may have swapped from a known to an unknown
144 * attribute. We still print out the unknown one.
145 */
146 if (ancestor && da->flags.is_unknown) {
147 fr_assert(da->depth > ancestor->depth);
148
149 ancestor = da_stack.da[ancestor->depth - 1];
150 }
151
152 if (ancestor) {
153 if (da_stack.da[ancestor->depth - 1] != ancestor) {
154 fr_strerror_printf("Attribute '%s' is not a descendent of \"%s\"", da->name, ancestor->name);
155 return 0;
156 }
157 depth = ancestor->depth;
158 }
159
160 /*
161 * We don't print the ancestor, we print the OID
162 * between it and the da.
163 */
164 if (numeric) {
165 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", da_stack.da[depth]->attr);
166 for (i = depth + 1; i < (int)da->depth; i++) {
167 FR_SBUFF_IN_CHAR_RETURN(&our_out, '.');
168 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", da_stack.da[i]->attr);
169 }
170 } else {
171 FR_SBUFF_IN_STRCPY_RETURN(&our_out, da_stack.da[depth]->name);
172 for (i = depth + 1; i < (int)da->depth; i++) {
173 FR_SBUFF_IN_CHAR_RETURN(&our_out, '.');
174 FR_SBUFF_IN_STRCPY_RETURN(&our_out, da_stack.da[i]->name);
175 }
176 }
177 FR_SBUFF_SET_RETURN(out, &our_out);
178}
179
180typedef struct {
181 FILE *fp;
183 char prefix[256];
184 char flags[256];
185 char oid[256];
186 unsigned int start_depth;
188
189static int dict_attr_debug(fr_dict_attr_t const *da, void *uctx)
190{
191 fr_dict_attr_debug_t *ctx = uctx;
192 fr_hash_iter_t iter;
193 fr_dict_enum_value_t const *enumv;
195
197 ctx->dict, da->type, &da->flags);
198
199 snprintf(ctx->prefix, sizeof(ctx->prefix),
200 "[%02u] 0x%016" PRIxPTR "%*s",
201 da->depth,
202 (unsigned long)da,
203 (da->depth - ctx->start_depth) * 4, "");
204
205 fprintf(ctx->fp, "%s%s(%u) %s %s\n",
206 ctx->prefix,
207 da->name,
208 da->attr,
209 fr_type_to_str(da->type),
210 ctx->flags);
211
212 dict_attr_ext_debug(ctx->prefix, da); /* Print all the extension debug info */
213
215 if (!ext || !ext->name_by_value) return 0;
216
217 for (enumv = fr_hash_table_iter_init(ext->name_by_value, &iter);
218 enumv;
219 enumv = fr_hash_table_iter_next(ext->name_by_value, &iter)) {
220 char *value = fr_asprintf(NULL, "%pV", enumv->value);
221
222 fprintf(ctx->fp, "%s %s -> %s\n",
223 ctx->prefix,
224 enumv->name,
225 value);
227 }
228
229 return 0;
230}
231
233{
234 fr_dict_attr_debug_t uctx = {
235 .fp = fp,
236 .dict = fr_dict_by_da(da),
237 .start_depth = da->depth,
238 };
239 fr_hash_table_t *namespace;
240 fr_hash_iter_t iter;
241 fr_dict_attr_t *our_da;
242
243 namespace = dict_attr_namespace(da);
244 if (!namespace) {
245 fprintf(fp, "%s does not have namespace\n", da->name);
246 return;
247 }
248
249 for (our_da = fr_hash_table_iter_init(namespace, &iter);
250 our_da;
251 our_da = fr_hash_table_iter_next(namespace, &iter)) {
252 dict_attr_debug(our_da, &uctx);
253 }
254}
255
256void fr_dict_attr_debug(FILE *fp, fr_dict_attr_t const *da)
257{
258 fr_dict_attr_debug_t uctx = {
259 .fp = fp,
260 .dict = fr_dict_by_da(da),
261 .start_depth = da->depth,
262 };
263
264 dict_attr_debug(da, &uctx);
265 (void)fr_dict_walk(da, dict_attr_debug, &uctx);
266}
267
268void fr_dict_debug(FILE *fp, fr_dict_t const *dict)
269{
271}
272
273static int dict_attr_export(fr_dict_attr_t const *da, void *uctx)
274{
275 fr_dict_attr_debug_t *ctx = uctx;
276
277 (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(ctx->prefix, sizeof(ctx->prefix)),
278 NULL, da, false);
279 (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(ctx->oid, sizeof(ctx->oid)),
280 NULL, da, true);
281
282 *ctx->flags = 0; /* some attributes don't have flags */
284 ctx->dict, da->type, &da->flags);
285 fprintf(ctx->fp, "ATTRIBUTE\t%-40s\t%-20s\t%s\t%s\n",
286 ctx->prefix,
287 ctx->oid,
288 fr_type_to_str(da->type),
289 ctx->flags);
290
291 return 0;
292}
293
294static void fr_dict_attr_export(FILE *fp, fr_dict_attr_t const *da)
295{
296 fr_dict_attr_debug_t uctx = {
297 .fp = fp,
298 .dict = fr_dict_by_da(da),
299 .start_depth = da->depth
300 };
301
302 dict_attr_export(da, &uctx);
303 (void)fr_dict_walk(da, dict_attr_export, &uctx);
304}
305
306/** Export in the standard form: ATTRIBUTE name oid flags
307 *
308 */
309void fr_dict_export(FILE *fp, fr_dict_t const *dict)
310{
312}
313
315{
316 fr_hash_table_t *namespace;
317 fr_hash_iter_t iter;
318 fr_dict_attr_t *da;
319 char buffer [256];
320
321 namespace = dict_attr_namespace(parent);
322 if (!namespace) {
323 fprintf(fp, "%s does not have namespace\n", parent->name);
324 return;
325 }
326
327 for (da = fr_hash_table_iter_init(namespace, &iter);
328 da;
329 da = fr_hash_table_iter_next(namespace, &iter)) {
330 fr_dict_attr_t const *ref;
331
332 if (!da->flags.is_alias) continue;
333
334 if (!fr_type_is_leaf(da->type)) continue;
335
336 ref = fr_dict_attr_ref(da);
337 if (!ref) continue;
338
339 if (da->depth == ref->depth) continue;
340
341#ifdef STATIC_ANALYZER
342 buffer[0] = '\0';
343#endif
344
346 NULL, ref, false);
347
348 fprintf(fp, "%-40s\t%s\n", da->name, buffer);
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:2681
int fr_dict_walk(fr_dict_attr_t const *da, fr_dict_walk_t callback, void *uctx)
Definition dict_util.c:4895
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2475
unsigned int extra
really "subtype is used by dict, not by protocol"
Definition dict.h:117
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:237
@ FLAG_LENGTH_UINT8
string / octets type is prefixed by uint8 of length
Definition dict.h:155
@ FLAG_LENGTH_UINT16
string / octets type is prefixed by uint16 of length
Definition dict.h:156
@ FLAG_KEY_FIELD
this is a key field for a subsequent struct
Definition dict.h:153
@ FLAG_BIT_FIELD
bit field inside of a struct
Definition dict.h:154
@ FR_DICT_ATTR_EXT_ENUMV
Enumeration values.
Definition dict.h:175
unsigned int is_unsigned
hackity hack for dates and time deltas
Definition dict.h:97
char const * name
Enum name.
Definition dict.h:234
uint8_t subtype
protocol-specific values, OR key fields
Definition dict.h:128
uint8_t length
length of the attribute
Definition dict.h:134
Values of the encryption flags.
Value of an enumerated attribute.
Definition dict.h:233
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:182
void fr_dict_namespace_debug(FILE *fp, fr_dict_attr_t const *da)
Definition dict_print.c:232
static int dict_attr_export(fr_dict_attr_t const *da, void *uctx)
Definition dict_print.c:273
void fr_dict_alias_export(FILE *fp, fr_dict_attr_t const *parent)
Definition dict_print.c:314
void fr_dict_debug(FILE *fp, fr_dict_t const *dict)
Definition dict_print.c:268
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:294
void fr_dict_attr_debug(FILE *fp, fr_dict_attr_t const *da)
Definition dict_print.c:256
unsigned int start_depth
Definition dict_print.c:186
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:189
void fr_dict_export(FILE *fp, fr_dict_t const *dict)
Export in the standard form: ATTRIBUTE name oid flags.
Definition dict_print.c:309
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:2156
#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:841
fr_dict_attr_t const * da[FR_DICT_MAX_TLV_STACK+1]
The stack.
Definition proto.h:57
Structure for holding the stack of dictionary attributes being encoded.
Definition proto.h:55
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_type_is_leaf(_x)
Definition types.h:391
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:452
#define FR_TYPE_FIXED_SIZE
Definition types.h:308
static size_t char ** out
Definition value.h:1023