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: cae96f2bdad6d111a6d5ae81184ce644bef89cf9 $")
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 {
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 *our_uctx = uctx;
190 fr_hash_iter_t iter;
191 fr_dict_enum_value_t const *enumv;
193
194 fr_dict_attr_flags_print(&FR_SBUFF_OUT(our_uctx->flags, sizeof(our_uctx->flags)),
195 our_uctx->dict, da->type, &da->flags);
196
197 snprintf(our_uctx->prefix, sizeof(our_uctx->prefix),
198 "[%02u] 0x%016" PRIxPTR "%*s",
199 da->depth,
200 (unsigned long)da,
201 (da->depth - our_uctx->start_depth) * 4, "");
202
203 FR_FAULT_LOG("%s%s(%u) %s %s",
204 our_uctx->prefix,
205 da->name,
206 da->attr,
207 fr_type_to_str(da->type),
208 our_uctx->flags);
209
210 dict_attr_ext_debug(our_uctx->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 FR_FAULT_LOG("%s %s -> %s",
221 our_uctx->prefix,
222 enumv->name,
223 value);
225 }
226
227 return 0;
228}
229
231{
232 fr_dict_attr_debug_t uctx = { .dict = fr_dict_by_da(da), .start_depth = da->depth };
233 fr_hash_table_t *namespace;
234 fr_hash_iter_t iter;
235 fr_dict_attr_t *our_da;
236
237 namespace = dict_attr_namespace(da);
238 if (!namespace) {
239 FR_FAULT_LOG("%s does not have namespace", da->name);
240 return;
241 }
242
243 for (our_da = fr_hash_table_iter_init(namespace, &iter);
244 our_da;
245 our_da = fr_hash_table_iter_next(namespace, &iter)) {
246 dict_attr_debug(our_da, &uctx);
247 }
248}
249
251{
252 fr_dict_attr_debug_t uctx = { .dict = fr_dict_by_da(da), .start_depth = da->depth };
253
254 dict_attr_debug(da, &uctx);
255 (void)fr_dict_walk(da, dict_attr_debug, &uctx);
256}
257
258void fr_dict_debug(fr_dict_t const *dict)
259{
261}
262
263static int dict_attr_export(fr_dict_attr_t const *da, void *uctx)
264{
265 fr_dict_attr_debug_t *our_uctx = uctx;
266
267 (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(our_uctx->prefix, sizeof(our_uctx->prefix)),
268 NULL, da, false);
269 (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(our_uctx->oid, sizeof(our_uctx->oid)),
270 NULL, da, true);
271 *our_uctx->flags = 0; /* some attributes don't have flags */
272 fr_dict_attr_flags_print(&FR_SBUFF_OUT(our_uctx->flags, sizeof(our_uctx->flags)),
273 our_uctx->dict, da->type, &da->flags);
274
275 FR_FAULT_LOG("ATTRIBUTE\t%-40s\t%-20s\t%s\t%s",
276 our_uctx->prefix,
277 our_uctx->oid,
278 fr_type_to_str(da->type),
279 our_uctx->flags);
280
281 return 0;
282}
283
285{
286 fr_dict_attr_debug_t uctx = { .dict = fr_dict_by_da(da), .start_depth = da->depth };
287
288 dict_attr_export(da, &uctx);
289 (void)fr_dict_walk(da, dict_attr_export, &uctx);
290}
291
292/** Export in the standard form: ATTRIBUTE name oid flags
293 *
294 */
295void fr_dict_export(fr_dict_t const *dict)
296{
298}
#define RCSID(id)
Definition build.h:483
#define FR_FAULT_LOG(_fmt,...)
Definition debug.h:49
@ FLAG_LENGTH_UINT8
string / octets type is prefixed by uint8 of length
Definition dict.h:149
@ FLAG_LENGTH_UINT16
string / octets type is prefixed by uint16 of length
Definition dict.h:150
@ FLAG_KEY_FIELD
this is a key field for a subsequent struct
Definition dict.h:147
@ FLAG_BIT_FIELD
bit field inside of a struct
Definition dict.h:148
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:2606
int fr_dict_walk(fr_dict_attr_t const *da, fr_dict_walk_t callback, void *uctx)
Definition dict_util.c:4777
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2400
unsigned int extra
really "subtype is used by dict, not by protocol"
Definition dict.h:113
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:231
@ FR_DICT_ATTR_EXT_ENUMV
Enumeration values.
Definition dict.h:169
unsigned int is_unsigned
hackity hack for dates and time deltas
Definition dict.h:95
char const * name
Enum name.
Definition dict.h:228
uint8_t subtype
protocol-specific values, OR key fields
Definition dict.h:122
uint8_t length
length of the attribute
Definition dict.h:128
Values of the encryption flags.
Value of an enumerated attribute.
Definition dict.h:227
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
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
static int dict_attr_export(fr_dict_attr_t const *da, void *uctx)
Definition dict_print.c:263
void fr_dict_namespace_debug(fr_dict_attr_t const *da)
Definition dict_print.c:230
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
void fr_dict_debug(fr_dict_t const *dict)
Definition dict_print.c:258
static void fr_dict_attr_export(fr_dict_attr_t const *da)
Definition dict_print.c:284
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:125
#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(fr_dict_t const *dict)
Export in the standard form: ATTRIBUTE name oid flags.
Definition dict_print.c:295
void fr_dict_attr_debug(fr_dict_attr_t const *da)
Definition dict_print.c:250
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
#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
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
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:997