The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_dict.c
Go to the documentation of this file.
1/*
2 * This program is 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 (at
5 * 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/**
18 * $Id: 8c4a99af55480c6f728b2353d5a14defd8d50611 $
19 * @file rlm_dict.c
20 * @brief Retrieve attributes from a dict.
21 *
22 * @copyright 2016 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 */
24RCSID("$Id: 8c4a99af55480c6f728b2353d5a14defd8d50611 $")
25
26#include <freeradius-devel/server/base.h>
27#include <freeradius-devel/server/module_rlm.h>
28#include <freeradius-devel/server/log.h>
29#include <freeradius-devel/util/debug.h>
30#include <freeradius-devel/util/sbuff.h>
31#include <freeradius-devel/util/value.h>
32#include <freeradius-devel/unlang/xlat.h>
33#include <freeradius-devel/unlang/xlat_func.h>
34
35/** Return a VP from the specified request.
36 *
37 * @param out where to write the pointer to the resolved VP. Will be NULL if the attribute couldn't
38 * be resolved.
39 * @param request current request.
40 * @param name attribute name including qualifiers.
41 * @return
42 * - -4 if either the attribute or qualifier were invalid.
43 * - The same error codes as #tmpl_find_vp for other error conditions.
44 */
45static int xlat_fmt_get_vp(fr_pair_t **out, request_t *request, char const *name)
46{
47 int ret;
48 tmpl_t *vpt;
49
50 *out = NULL;
51
52 if (tmpl_afrom_attr_str(request, NULL, &vpt, name,
53 &(tmpl_rules_t){
54 .attr = {
55 .dict_def = request->dict,
56 .list_def = request_attr_request,
58 }
59 }) <= 0) return -4;
60
61 ret = tmpl_find_vp(out, request, vpt);
63
64 return ret;
65}
66
67
69 { .required = true, .single = true, .type = FR_TYPE_UINT32 },
71};
72
73/** Xlat for %attr_by_num(<number>)
74 *
75 * @ingroup xlat_functions
76 */
78 UNUSED xlat_ctx_t const *xctx,
79 request_t *request, fr_value_box_list_t *in)
80{
81 fr_dict_attr_t const *da;
82 fr_value_box_t *attr = fr_value_box_list_head(in);
84
85 da = fr_dict_attr_child_by_num(fr_dict_root(request->dict), attr->vb_uint32);
86 if (!da) {
87 REDEBUG("No attribute found with number %pV", attr);
88 return XLAT_ACTION_FAIL;
89 }
90
92
93 if (fr_value_box_bstrndup(vb, vb, NULL, da->name, strlen(da->name), false) < 0) {
94 talloc_free(vb);
95 return XLAT_ACTION_FAIL;
96 }
97
99 return XLAT_ACTION_DONE;
100}
101
103 { .required = true, .single = true, .type = FR_TYPE_STRING },
105};
106
107/** Xlat for %attr_by_oid(<oid>)
108 *
109 * @ingroup xlat_functions
110 */
112 UNUSED xlat_ctx_t const *xctx,
113 request_t *request, fr_value_box_list_t *in)
114{
115 unsigned int attr = 0;
116 fr_dict_attr_t const *parent = fr_dict_root(request->dict);
117 fr_dict_attr_t const *da;
118 ssize_t ret;
119 fr_value_box_t *attr_vb = fr_value_box_list_head(in);
120 fr_value_box_t *vb;
121
122 ret = fr_dict_attr_by_oid_legacy(fr_dict_internal(), &parent, &attr, attr_vb->vb_strvalue);
123 if (ret <= 0) {
124 REMARKER(attr_vb->vb_strvalue, -(ret), "%s", fr_strerror());
125 return XLAT_ACTION_FAIL;
126 }
127
129 if (!da) {
130 RDEBUG("Parent %s has no child %u", parent->name, attr);
131 return XLAT_ACTION_FAIL;
132 }
133
134 MEM(vb = fr_value_box_alloc_null(ctx));
135
136 if (fr_value_box_bstrndup(vb, vb, NULL, da->name, strlen(da->name), false) < 0) {
137 talloc_free(vb);
138 return XLAT_ACTION_FAIL;
139 }
140
142 return XLAT_ACTION_DONE;
143}
144
146 { .required = true, .single = true, .type = FR_TYPE_STRING },
148};
149
150/** Return the vendor of an attribute reference
151 *
152 * @ingroup xlat_functions
153 */
154static xlat_action_t xlat_vendor(TALLOC_CTX *ctx, fr_dcursor_t *out,
155 UNUSED xlat_ctx_t const *xctx,
156 request_t *request, fr_value_box_list_t *in)
157{
158 fr_pair_t *vp;
159 fr_dict_vendor_t const *vendor;
160 fr_value_box_t *attr = fr_value_box_list_head(in);
161 fr_value_box_t *vb;
162
163 if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
164
165 vendor = fr_dict_vendor_by_da(vp->da);
166 if (!vendor) return XLAT_ACTION_FAIL;
167
168 MEM(vb = fr_value_box_alloc_null(ctx));
169
170 if (fr_value_box_bstrndup(vb, vb, NULL, vendor->name, strlen(vendor->name), false) < 0) {
171 talloc_free(vb);
172 return XLAT_ACTION_FAIL;
173 }
174
176 return XLAT_ACTION_DONE;
177}
178
180 { .required = true, .single = true, .type = FR_TYPE_STRING },
182};
183
184/** Return the vendor number of an attribute reference
185 *
186 * @ingroup xlat_functions
187 */
189 UNUSED xlat_ctx_t const *xctx,
190 request_t *request, fr_value_box_list_t *in)
191{
192 fr_pair_t *vp;
193 fr_value_box_t *attr = fr_value_box_list_head(in);
194 fr_value_box_t *vb;
195
196 if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
197
198 MEM(vb = fr_value_box_alloc_null(ctx));
199 fr_value_box_uint32(vb, NULL, fr_dict_vendor_num_by_da(vp->da), false);
201 return XLAT_ACTION_DONE;
202}
203
205 { .required = true, .single = true, .type = FR_TYPE_STRING },
207};
208
209/** Return the attribute name of an attribute reference
210 *
211 * @ingroup xlat_functions
212 */
213static xlat_action_t xlat_attr(TALLOC_CTX *ctx, fr_dcursor_t *out,
214 UNUSED xlat_ctx_t const *xctx,
215 request_t *request, fr_value_box_list_t *in)
216{
217 fr_pair_t *vp;
218 fr_value_box_t *attr = fr_value_box_list_head(in);
219 fr_value_box_t *vb;
220
221 if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
222
223 MEM(vb = fr_value_box_alloc_null(ctx));
224
225 if (fr_value_box_bstrndup(vb, vb, NULL, vp->da->name, strlen(vp->da->name), false) < 0) {
226 talloc_free(vb);
227 return XLAT_ACTION_FAIL;
228 }
229
231 return XLAT_ACTION_DONE;
232}
233
235 { .required = true, .single = true, .type = FR_TYPE_STRING },
237};
238
239/** Return the attribute number of an attribute reference
240 *
241 * @ingroup xlat_functions
242 */
244 UNUSED xlat_ctx_t const *xctx,
245 request_t *request, fr_value_box_list_t *in)
246{
247 fr_pair_t *vp;
248 fr_value_box_t *attr = fr_value_box_list_head(in);
249 fr_value_box_t *vb;
250
251 if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
252
253 MEM(vb = fr_value_box_alloc_null(ctx));
254
255 fr_value_box_uint32(vb, NULL, vp->da->attr, false);
257 return XLAT_ACTION_DONE;
258}
259
261 { .required = true, .single = true, .type = FR_TYPE_STRING },
263};
264
265/** Return the attribute number of an attribute reference
266 *
267 * @ingroup xlat_functions
268 */
270 UNUSED xlat_ctx_t const *xctx,
271 request_t *request, fr_value_box_list_t *in)
272{
273 fr_pair_t *vp;
274 fr_value_box_t *attr = fr_value_box_list_head(in);
275 fr_value_box_t *vb;
276 fr_sbuff_t *oid_buff;
277
278 FR_SBUFF_TALLOC_THREAD_LOCAL(&oid_buff, 50, SIZE_MAX);
279
280 if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
281
282 MEM(vb = fr_value_box_alloc_null(ctx));
283
284 /*
285 * Print to an extendable buffer, so we don't have to worry
286 * about the size of the OID.
287 */
288 if (fr_dict_attr_oid_print(oid_buff, NULL, vp->da, true) < 0) {
289 RPEDEBUG("Printing OID for '%s' failed", vp->da->name);
290 return XLAT_ACTION_FAIL;
291 }
292
293 fr_value_box_strdup(vb, vb, NULL, fr_sbuff_start(oid_buff), false);
295
296 return XLAT_ACTION_DONE;
297}
298
299/** Return the data type of an attribute reference
300 *
301 * @ingroup xlat_functions
302 */
304 UNUSED xlat_ctx_t const *xctx,
305 request_t *request, fr_value_box_list_t *in)
306{
307 fr_pair_t *vp;
308 fr_value_box_t *attr = fr_value_box_list_head(in);
309 fr_value_box_t *vb;
310
311 if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
312
313 MEM(vb = fr_value_box_alloc_null(ctx));
314
315 fr_value_box_strdup(vb, vb, vp->da, fr_type_to_str(vp->vp_type), false);
317 return XLAT_ACTION_DONE;
318}
319
320#define XLAT_REGISTER(_name, _func, _type, _args) \
321if (unlikely(!(xlat = xlat_func_register(NULL, _name, _func, _type)))) return -1; \
322xlat_func_args_set(xlat, _args)
323
338
339static void mod_unload(void)
340{
341 xlat_func_unregister("dict.attr.by_num");
342 xlat_func_unregister("dict.attr.by_oid");
343 xlat_func_unregister("dict.vendor");
344 xlat_func_unregister("dict.vendor.num");
345 xlat_func_unregister("dict.attr");
346 xlat_func_unregister("dict.attr.num");
347 xlat_func_unregister("dict.attr.oid");
348 xlat_func_unregister("dict.attr.type");
349}
350
353 .common = {
354 .magic = MODULE_MAGIC_INIT,
355 .name = "dict",
356 .onload = mod_load,
357 .unload = mod_unload
358 }
359};
#define RCSID(id)
Definition build.h:483
#define UNUSED
Definition build.h:315
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
#define MEM(x)
Definition debug.h:36
char const * name
Vendor name.
Definition dict.h:252
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
fr_slen_t fr_dict_attr_by_oid_legacy(fr_dict_t const *dict, fr_dict_attr_t const **parent, unsigned int *attr, char const *oid)
Get the leaf attribute of an OID string.
Definition dict_util.c:2132
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4617
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition dict_util.c:3335
static fr_slen_t in
Definition dict.h:827
fr_dict_vendor_t const * fr_dict_vendor_by_da(fr_dict_attr_t const *da)
Look up a vendor by one of its child attributes.
Definition dict_util.c:2642
Private enterprise.
Definition dict.h:247
static uint32_t fr_dict_vendor_num_by_da(fr_dict_attr_t const *da)
Return the vendor number for an attribute.
Definition dict_ext.h:212
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
static xlat_action_t xlat_attr_num(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the attribute number of an attribute reference.
Definition rlm_dict.c:243
static xlat_action_t xlat_dict_attr_by_num(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Xlat for attr_by_num(<number>)
Definition rlm_dict.c:77
static xlat_action_t xlat_attr(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the attribute name of an attribute reference.
Definition rlm_dict.c:213
static xlat_action_t xlat_attr_oid(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the attribute number of an attribute reference.
Definition rlm_dict.c:269
static xlat_action_t xlat_attr_type(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the data type of an attribute reference.
Definition rlm_dict.c:303
static xlat_action_t xlat_dict_attr_by_oid(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Xlat for attr_by_oid(<oid>)
Definition rlm_dict.c:111
static xlat_action_t xlat_vendor_num(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the vendor number of an attribute reference.
Definition rlm_dict.c:188
static xlat_action_t xlat_vendor(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the vendor of an attribute reference.
Definition rlm_dict.c:154
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:498
#define RPEDEBUG(fmt,...)
Definition log.h:376
talloc_free(reap)
@ TMPL_ATTR_REF_PREFIX_AUTO
Attribute refs may have a '&' prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
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)
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG(fmt,...)
Definition radclient.h:53
fr_dict_attr_t const * request_attr_request
Definition request.c:45
static xlat_arg_parser_t const xlat_attr_oid_args[]
Definition rlm_dict.c:260
static xlat_arg_parser_t const xlat_vendor_num_args[]
Definition rlm_dict.c:179
static int mod_load(void)
Definition rlm_dict.c:324
static xlat_arg_parser_t const xlat_attr_num_args[]
Definition rlm_dict.c:234
static xlat_arg_parser_t const xlat_vendor_args[]
Definition rlm_dict.c:145
static xlat_arg_parser_t const xlat_attr_args[]
Definition rlm_dict.c:204
static xlat_arg_parser_t const xlat_dict_attr_by_oid_args[]
Definition rlm_dict.c:102
#define XLAT_REGISTER(_name, _func, _type, _args)
Definition rlm_dict.c:320
static void mod_unload(void)
Definition rlm_dict.c:339
static xlat_arg_parser_t const xlat_dict_attr_by_num_args[]
Definition rlm_dict.c:68
module_rlm_t rlm_dict
Definition rlm_dict.c:352
static int xlat_fmt_get_vp(fr_pair_t **out, request_t *request, char const *name)
Return a VP from the specified request.
Definition rlm_dict.c:45
static char const * name
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
int tmpl_find_vp(fr_pair_t **out, request_t *request, tmpl_t const *vpt))
Returns the first VP matching a tmpl_t.
Definition tmpl_eval.c:889
static fr_slen_t vpt
Definition tmpl.h:1276
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:347
fr_pair_t * vp
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
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:168
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumend by an xlat function.
Definition xlat.h:147
static fr_slen_t parent
Definition pair.h:851
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:433
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
Definition value.c:3937
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
Definition value.c:4158
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:632
static size_t char ** out
Definition value.h:997
An xlat calling ctx.
Definition xlat_ctx.h:49
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:519