The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
map.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 (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: 3db234257e14ee50e4f366f8ca3711892701d286 $
19 * @file src/lib/ldap/map.c
20 * @brief Functions for mapping between LDAP and FreeRADIUS attributes.
21 *
22 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 * @copyright 2013 Network RADIUS SAS (legal@networkradius.com)
24 * @copyright 2013 The FreeRADIUS Server Project.
25 */
26RCSID("$Id: 3db234257e14ee50e4f366f8ca3711892701d286 $")
27
29
30#include <freeradius-devel/util/debug.h>
31#include <freeradius-devel/ldap/base.h>
32
33/** Callback for map_to_request
34 *
35 * Performs exactly the same job as map_to_vp, but pulls attribute values from LDAP entries
36 *
37 * @see map_to_vp
38 */
39int fr_ldap_map_getvalue(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
40{
41 fr_ldap_value_iter_t *iter = talloc_get_type_abort(uctx, fr_ldap_value_iter_t);
42 struct berval *value;
45 int err = 0;
46
48
49 fr_assert(map->lhs->type == TMPL_TYPE_ATTR);
50
51 /*
52 * This is a mapping in the form of:
53 * <list>. += <ldap attr>
54 *
55 * Where <ldap attr> is:
56 * <list>.<attr> <op> <value>
57 *
58 * It is to allow for legacy installations which stored
59 * RADIUS control and reply attributes in separate LDAP
60 * attributes.
61 */
62 if (tmpl_is_list(map->lhs)) {
63 /*
64 * The caller's iterator init consumed the first value,
65 * still available as iter->value.
66 */
67 for (value = &iter->value; value; value = fr_ldap_value_iter_next(&err, iter)) {
68 map_t *attr = NULL;
69 char *attr_str;
70
71 tmpl_rules_t lhs_rules = {
72 .attr = {
73 .dict_def = request->local_dict,
74 .request_def = tmpl_request(map->lhs),
75 .list_def = tmpl_list(map->lhs),
76 },
77 .xlat = {
78 .runtime_el = unlang_interpret_event_list(request),
79 },
80 .at_runtime = true,
81 };
82
83 tmpl_rules_t rhs_rules = {
84 .attr = {
85 .dict_def = request->local_dict
86 },
87 .xlat = {
88 .runtime_el = lhs_rules.xlat.runtime_el,
89 },
90 .at_runtime = true,
91 };
92
93 RDEBUG3("Parsing valuepair string \"%pV\"",
94 fr_box_strvalue_len(value->bv_val, value->bv_len));
95
96 /*
97 * bv_val is NOT \0 terminated, so we need to make it
98 * safe (\0 terminate it) before passing it to any
99 * functions which take C strings and no lengths.
100 */
101 attr_str = talloc_bstrndup(NULL, value->bv_val, value->bv_len);
102 if (!attr_str) {
103 RWDEBUG("Failed making attribute string safe");
104 continue;
105 }
106
107 if (map_afrom_attr_str(ctx, &attr,
108 attr_str,
109 &lhs_rules, &rhs_rules) < 0) {
110 RPWDEBUG("Failed parsing \"%pV\" as valuepair, skipping...",
111 fr_box_strvalue_len(value->bv_val, value->bv_len));
112 talloc_free(attr_str);
113 continue;
114 }
115
116 talloc_free(attr_str);
117
118 if (tmpl_is_data_unresolved(attr->lhs)) {
119 RWDEBUG("Failed parsing left side of \"%pV\", skipping...",
120 fr_box_strvalue_len(value->bv_val, value->bv_len));
121 talloc_free(attr);
122 continue;
123 }
124
125 if (tmpl_request_ref_list_cmp(tmpl_request(attr->lhs), tmpl_request(map->lhs)) != 0) {
126 char *attr_request;
127 char *map_request;
128
129 tmpl_request_ref_list_aprint(NULL, &attr_request, tmpl_request(attr->lhs));
130 tmpl_request_ref_list_aprint(NULL, &map_request, tmpl_request(map->lhs));
131
132 RWDEBUG("valuepair \"%pV\" has conflicting request qualifier (%s vs %s), skipping...",
133 fr_box_strvalue_len(value->bv_val, value->bv_len),
134 attr_request, map_request);
135
136 talloc_free(attr_request);
137 talloc_free(map_request);
138
139 next_pair:
140 talloc_free(attr);
141 continue;
142 }
143
144 if ((tmpl_list(attr->lhs) != tmpl_list(map->lhs))) {
145 RWDEBUG("valuepair \"%pV\" has conflicting list qualifier (%s vs %s), skipping...",
146 fr_box_strvalue_len(value->bv_val, value->bv_len),
147 tmpl_list_name(tmpl_list(attr->lhs), "<INVALID>"),
148 tmpl_list_name(tmpl_list(map->lhs), "<INVALID>"));
149 goto next_pair;
150 }
151
152 if (map_to_request(request, attr, map_to_vp, NULL) < 0) {
153 RWDEBUG("Failed creating attribute for valuepair \"%pV\", skipping...",
154 fr_box_strvalue_len(value->bv_val, value->bv_len));
155 goto next_pair;
156 }
157
158 talloc_free(attr);
159
160 /*
161 * Only process the first value, unless the operator is +=
162 */
163 if (map->op != T_OP_ADD_EQ) break;
164 }
165 goto finish;
166 }
167
168 /*
169 * Iterate over all the retrieved values,
170 * don't try and be clever about changing operators
171 * just use whatever was set in the attribute map.
172 */
173 for (value = &iter->value; value; value = fr_ldap_value_iter_next(&err, iter)) {
174 if (!value->bv_len) continue;
175
177
178 if (fr_pair_value_from_str(vp, value->bv_val,
179 value->bv_len, NULL, true) < 0) {
180 RPWDEBUG("Failed parsing value \"%pV\" for attribute %s",
181 fr_box_strvalue_len(value->bv_val, value->bv_len),
182 tmpl_attr_tail_da(map->lhs)->name);
183
185 continue;
186 }
187
189
190 /*
191 * Only process the first value, unless the operator is +=
192 */
193 if (map->op != T_OP_ADD_EQ) break;
194 }
195
196finish:
197 if (unlikely(err < 0)) return -1;
198
200
201 return 0;
202}
203
204/** Callback for map_to_request
205 *
206 * Performs exactly the same job as map_to_vp, but pulls value from the entry DN.
207 *
208 * @see map_to_vp
209 */
210int fr_ldap_map_getdn(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
211{
212 char const *dn = uctx;
213 fr_pair_t *vp;
214
215 fr_assert(map->lhs->type == TMPL_TYPE_ATTR);
216 switch (tmpl_attr_tail_da(map->lhs)->type) {
217 case FR_TYPE_STRING:
218 case FR_TYPE_OCTETS:
219 break;
220
221 default:
222 RERROR("Cannot store DN in %s",
223 fr_table_str_by_value(fr_type_table, tmpl_attr_tail_da(map->lhs)->type, "<INVALID>"));
224 return -1;
225 }
226
228
229 if (fr_pair_value_from_str(vp, dn, strlen(dn), NULL, true) < 0) {
230 RPWDEBUG("Failed parsing value \"%pV\" for attribute %s", dn,
231 tmpl_attr_tail_da(map->lhs)->name);
233 return 0;
234 }
235
237
238 return 0;
239}
240
241int fr_ldap_map_verify(map_t *map, UNUSED void *instance)
242{
243 /*
244 * Destinations where we can put the fr_pair_ts we
245 * create using LDAP values.
246 */
247 switch (map->lhs->type) {
248 case TMPL_TYPE_ATTR:
249 break;
250
252 cf_log_err(map->ci, "Unknown attribute %s", tmpl_attr_tail_unresolved(map->lhs));
253 return -1;
254
255 default:
256 cf_log_err(map->ci, "Left hand side of map must be an attribute or list, not a %s",
257 tmpl_type_to_str(map->lhs->type));
258 return -1;
259 }
260
261 /*
262 * Sources we can use to get the name of the attribute
263 * we're retrieving from LDAP.
264 */
265 switch (map->rhs->type) {
267 case TMPL_TYPE_ATTR:
268 case TMPL_TYPE_EXEC:
269 case TMPL_TYPE_DATA:
270 break;
271
273 cf_log_err(map->ci, "Unknown attribute %s", tmpl_attr_tail_unresolved(map->rhs));
274 return -1;
275
277 if (tmpl_resolve(map->rhs, NULL) < 0) {
278 cf_log_err(map->ci, "Invalid data %s", map->rhs->name);
279 return -1;
280 }
281 break;
282
283 default:
284 cf_log_err(map->ci, "Right hand side of map must be an xlat, attribute, exec, or literal, not a %s",
285 tmpl_type_to_str(map->rhs->type));
286 return -1;
287 }
288
289 /*
290 * Only =, :=, += and -= operators are supported for LDAP mappings.
291 */
292 switch (map->op) {
293 case T_OP_SET:
294 case T_OP_EQ:
295 case T_OP_SUB_EQ:
296 case T_OP_ADD_EQ:
297 break;
298
299 default:
300 cf_log_err(map->ci, "Operator \"%s\" not allowed for LDAP mappings",
301 fr_table_str_by_value(fr_tokens_table, map->op, "<INVALID>"));
302 return -1;
303 }
304
305 return 0;
306}
307
308/** Expand values in an attribute map where needed
309 *
310 * @param[in] ctx o allocate any dynamic expansions in.
311 * @param[out] expanded array of attributes. Need not be initialised (we'll initialise).
312 * @param[in] request The current request.
313 * @param[in] maps to expand.
314 * @param[in] generic_attr name to append to the attribute list.
315 * @param[in] check_attr name to append to the attribute list.
316 * @param[in] fallthrough_attr name to append to the attribute list.
317 * @return
318 * - 0 on success.
319 * - -1 on failure.
320 */
321int fr_ldap_map_expand(TALLOC_CTX *ctx, fr_ldap_map_exp_t *expanded, request_t *request, map_list_t const *maps,
322 char const *generic_attr, char const *check_attr, char const *fallthrough_attr)
323{
324 map_t const *map = NULL;
325 unsigned int total = 0;
326
327 TALLOC_CTX *our_ctx = NULL;
328 char const *attr;
329 char attr_buff[1024 + 1]; /* X.501 says we need to support at least 1024 chars for attr names */
330
331 while ((map = map_list_next(maps, map))) {
332 if (tmpl_expand(&attr, attr_buff, sizeof(attr_buff), request, map->rhs) < 0) {
333 REDEBUG("Expansion of LDAP attribute \"%s\" failed", map->rhs->name);
334 TALLOC_FREE(our_ctx);
335 return -1;
336 }
337
338 /*
339 * Dynamic value
340 */
341 if (attr == attr_buff) {
342 if (!our_ctx) our_ctx = talloc_new(ctx);
343 expanded->attrs[total++] = talloc_strdup(our_ctx, attr_buff);
344 continue;
345 }
346 expanded->attrs[total++] = attr;
347 }
348
349 if (generic_attr) expanded->attrs[total++] = generic_attr;
350 if (check_attr) expanded->attrs[total++] = check_attr;
351 if (fallthrough_attr) expanded->attrs[total++] = fallthrough_attr;
352
353 expanded->attrs[total] = NULL;
354 expanded->count = total;
355 expanded->maps = maps;
356
357 return 0;
358}
359
360
361/** Convert attribute map into valuepairs
362 *
363 * Use the attribute map built earlier to convert LDAP values into valuepairs and insert them into whichever
364 * list they need to go into.
365 *
366 * This is *NOT* atomic, but there's no condition for which we should error out...
367 *
368 * @param[in] request Current request.
369 * @param[in] check_attr Treat attribute with this name as a condition to process the map.
370 * @param[in] valuepair_attr Treat attribute with this name as holding complete AVP definitions.
371 * @param[in] expanded attributes (rhs of map).
372 * @param[in] entry to retrieve attributes from.
373 * @return
374 * - Number of maps successfully applied.
375 * - -1 on failure.
376 */
377int fr_ldap_map_do(request_t *request, char const *check_attr,
378 char const *valuepair_attr, fr_ldap_map_exp_t const *expanded, LDAPMessage *entry)
379{
380 map_t const *map = NULL;
381 unsigned int total = 0;
382 int applied = 0; /* How many maps have been applied to the current request */
383
384 char const *name;
385 LDAP *handle = fr_ldap_handle_thread_local();
386
387 if (check_attr) {
389 struct berval *check_value;
390 int iter_err = 0;
391 tmpl_rules_t const parse_rules = {
392 .attr = {
393 .dict_def = request->local_dict,
394 .list_def = request_attr_request,
395 },
396 .xlat = {
397 .runtime_el = unlang_interpret_event_list(request),
398 },
399 .at_runtime = true,
400 };
401
402 for (check_value = fr_ldap_value_iter_init(&iter_err, &iter, handle, entry, check_attr);
403 check_value;
404 check_value = fr_ldap_value_iter_next(&iter_err, &iter)) {
405 char *value = fr_ldap_berval_to_string(request, check_value);
406 xlat_exp_head_t *cond_expr = NULL;
407 fr_value_box_list_t res;
408
409 RDEBUG3("Parsing condition %s", value);
410
411 if (xlat_tokenize_expression(request, &cond_expr,
413 NULL, &parse_rules) < 0) {
414 RPEDEBUG("Failed parsing '%s' value \"%s\"", check_attr, value);
415 fail:
416 applied = -1;
417 free:
418 talloc_free(cond_expr);
421 return applied;
422 }
423
424 if (xlat_impure_func(cond_expr)) {
425 fr_strerror_const("Condition expression cannot depend on functions which call external databases");
426 goto fail;
427 }
428
429 RDEBUG2("Checking condition %s", value);
430 fr_value_box_list_init(&res);
431 if (unlang_xlat_eval(request, &res, request, cond_expr) < 0) {
432 RPEDEBUG("Failed evaluating condition");
433 goto fail;
434 }
435 if (!fr_value_box_list_head(&res) || !fr_value_box_is_truthy(fr_value_box_list_head(&res))) {
436 RDEBUG2("Failed match: skipping this profile");
437 fr_value_box_list_talloc_free(&res);
438 goto free;
439 }
441 talloc_free(cond_expr);
442 fr_value_box_list_talloc_free(&res);
443 }
445 if (unlikely(iter_err < 0)) {
446 RPERROR("Failed parsing entry");
447 return -1;
448 }
449 }
450
451 while ((map = map_list_next(expanded->maps, map))) {
453 int ret, iter_err = 0;
454
455 name = expanded->attrs[total++];
456
457 if (!fr_ldap_value_iter_alloc(&iter_err, &iter, request, handle, entry, name)) {
458 talloc_free(iter);
459 if (unlikely(iter_err < 0)) {
460 RPERROR("Failed parsing entry");
461 return -1;
462 }
463
464 /*
465 * dn is different - it's not (normally) an LDAP attribute
466 * so requires special handling.
467 */
468 if (strcmp(name, LDAP_VIRTUAL_DN_ATTR) == 0) {
469 char *dn = ldap_get_dn(handle, entry);
471 ret = map_to_request(request, map, fr_ldap_map_getdn, dn);
472 ldap_memfree(dn);
473 if (ret == -1) return -1;
474 applied++;
475 continue;
476 }
477
478 RDEBUG3("Attribute \"%s\" not found in LDAP object", name);
479 continue;
480 }
481
482 /*
483 * If something bad happened, just skip, this is probably
484 * a case of the dst being incorrect for the current
485 * request context
486 */
487 ret = map_to_request(request, map, fr_ldap_map_getvalue, iter);
488 talloc_free(iter);
489 if (ret == -1) return -1; /* Fail */
490
491 /*
492 * How many maps we've processed
493 */
494 applied++;
495 }
496
497
498 /*
499 * Retrieve any valuepair attributes from the result, these are generic values specifying
500 * a radius list, operator and value.
501 */
502 if (valuepair_attr) {
504 struct berval *vp_value;
505 int iter_err = 0;
506
507 for (vp_value = fr_ldap_value_iter_init(&iter_err, &iter, handle, entry, valuepair_attr);
508 vp_value;
509 vp_value = fr_ldap_value_iter_next(&iter_err, &iter)) {
510 map_t *attr;
511 char *value;
512
513 tmpl_rules_t const parse_rules = {
514 .attr = {
515 .dict_def = request->local_dict,
516 .list_def = request_attr_request,
517 },
518 .xlat = {
519 .runtime_el = unlang_interpret_event_list(request),
520 },
521 .at_runtime = true,
522 };
523
524 value = fr_ldap_berval_to_string(request, vp_value);
525 RDEBUG3("Parsing attribute string '%s'", value);
526 if (map_afrom_attr_str(request, &attr, value,
527 &parse_rules, &parse_rules) < 0) {
528 RPWDEBUG("Failed parsing '%s' value \"%s\" as valuepair, skipping...",
529 valuepair_attr, value);
531 continue;
532 }
533 if (map_to_request(request, attr, map_to_vp, NULL) < 0) {
534 RWDEBUG("Failed adding \"%s\" to request, skipping...", value);
535 } else {
536 applied++;
537 }
538 talloc_free(attr);
540 }
542 if (unlikely(iter_err < 0)) {
543 RPERROR("Failed parsing entry");
544 return -1;
545 }
546 }
547
548 return applied;
549}
#define USES_APPLE_DEPRECATED_API
Definition build.h:499
#define RCSID(id)
Definition build.h:512
#define unlikely(_x)
Definition build.h:407
#define UNUSED
Definition build.h:336
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:345
#define MEM(x)
Definition debug.h:36
static fr_slen_t err
Definition dict.h:882
Test enumeration values.
Definition dict_test.h:92
free(array)
talloc_free(hp)
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:2418
struct berval * fr_ldap_value_iter_init(int *err, fr_ldap_value_iter_t *iter, LDAP *handle, LDAPMessage *entry, char const *attr)
Start an in place iteration over an attribute's values in an entry.
Definition util.c:556
size_t fr_ldap_util_normalise_dn(char *out, char const *in)
Normalise escape sequences in a DN.
Definition util.c:827
int count
Index on next free element.
Definition base.h:376
void fr_ldap_value_iter_done(fr_ldap_value_iter_t *iter)
Release value iteration state.
Definition util.c:507
map_list_t const * maps
Head of list of maps we expanded the RHS of.
Definition base.h:372
struct berval * fr_ldap_value_iter_next(int *err, fr_ldap_value_iter_t *iter)
Return the next value of the iterated attribute.
Definition util.c:523
char * fr_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in)
Convert a berval to a talloced string.
Definition util.c:778
#define LDAP_VIRTUAL_DN_ATTR
'Virtual' attribute which maps to the DN of the object.
Definition base.h:113
char const * attrs[LDAP_MAX_ATTRMAP+LDAP_MAP_RESERVED+1]
Reserve some space for access attributes.
Definition base.h:373
struct berval * fr_ldap_value_iter_alloc(int *err, fr_ldap_value_iter_t **out, TALLOC_CTX *ctx, LDAP *handle, LDAPMessage *entry, char const *attr)
Allocate a value iterator, released when the iterator is freed.
Definition util.c:623
struct berval value
Value the iterator is positioned on.
Definition base.h:972
Result of expanding the RHS of a set of maps.
Definition base.h:371
State of an in place iteration over an attribute's values.
Definition base.h:968
LDAP * fr_ldap_handle_thread_local(void)
Get a thread local dummy LDAP handle.
Definition base.c:1130
int fr_ldap_map_do(request_t *request, char const *check_attr, char const *valuepair_attr, fr_ldap_map_exp_t const *expanded, LDAPMessage *entry)
Convert attribute map into valuepairs.
Definition map.c:377
int fr_ldap_map_getdn(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
Callback for map_to_request.
Definition map.c:210
USES_APPLE_DEPRECATED_API int fr_ldap_map_getvalue(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
Callback for map_to_request.
Definition map.c:39
int fr_ldap_map_verify(map_t *map, UNUSED void *instance)
Definition map.c:241
int fr_ldap_map_expand(TALLOC_CTX *ctx, fr_ldap_map_exp_t *expanded, request_t *request, map_list_t const *maps, char const *generic_attr, char const *check_attr, char const *fallthrough_attr)
Expand values in an attribute map where needed.
Definition map.c:321
#define RWDEBUG(fmt,...)
Definition log.h:373
#define RDEBUG3(fmt,...)
Definition log.h:355
#define RERROR(fmt,...)
Definition log.h:310
#define RPERROR(fmt,...)
Definition log.h:314
#define RPEDEBUG(fmt,...)
Definition log.h:388
#define RPWDEBUG(fmt,...)
Definition log.h:378
int map_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, UNUSED void *uctx)
Convert a map to a fr_pair_t.
Definition map.c:1604
int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert map_t to fr_pair_t (s) and add them to a request_t.
Definition map.c:1884
int map_afrom_attr_str(TALLOC_CTX *ctx, map_t **out, char const *vp_str, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules)
Convert a value pair string to valuepair map.
Definition map.c:1433
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_OCTETS
Raw octets.
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, UNUSED bool tainted)
Convert string value to native attribute value.
Definition pair.c:2617
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1352
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:290
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
fr_dict_attr_t const * request_attr_request
Definition request.c:43
static char const * name
#define FR_SBUFF_IN(_start, _len_or_end)
int8_t tmpl_request_ref_list_cmp(FR_DLIST_HEAD(tmpl_request_list) const *a, FR_DLIST_HEAD(tmpl_request_list) const *b)
Compare a list of request qualifiers.
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
Definition tmpl.h:638
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
Definition tmpl.h:904
static fr_slen_t tmpl_request_ref_list_aprint(TALLOC_CTX *ctx, char **out, FR_DLIST_HEAD(tmpl_request_list) const *rql) 1(tmpl_request_ref_list_print
@ TMPL_TYPE_ATTR_UNRESOLVED
An attribute reference that we couldn't resolve but looked valid.
Definition tmpl.h:185
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition tmpl.h:142
@ TMPL_TYPE_EXEC
Callout to an external script or program.
Definition tmpl.h:150
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:138
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
Definition tmpl.h:179
@ TMPL_TYPE_XLAT_UNRESOLVED
A xlat expansion with unresolved xlat functions or attribute references.
Definition tmpl.h:193
tmpl_xlat_rules_t xlat
Rules/data for parsing xlats.
Definition tmpl.h:340
static char const * tmpl_attr_tail_unresolved(tmpl_t const *vpt)
Return the last attribute reference unresolved da.
Definition tmpl.h:869
static bool tmpl_is_list(tmpl_t const *vpt)
Definition tmpl.h:920
#define tmpl_expand(_out, _buff, _buff_len, _request, _vpt)
Expand a tmpl to a C type, using existing storage to hold variably sized types.
Definition tmpl.h:1054
#define tmpl_is_data_unresolved(vpt)
Definition tmpl.h:217
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:339
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:801
static char const * tmpl_list_name(fr_dict_attr_t const *list, char const *def)
Return the name of a tmpl list or def if list not provided.
Definition tmpl.h:915
fr_event_list_t * runtime_el
The eventlist to use for runtime instantiation of xlats.
Definition tmpl.h:328
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
fr_pair_t * vp
Value pair map.
Definition map.h:77
fr_token_t op
The operator that controls insertion of the dst attribute.
Definition map.h:82
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
Definition map.h:78
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Definition map.h:79
CONF_ITEM * ci
Config item that the map was created from.
Definition map.h:85
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:273
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition talloc.c:618
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
fr_table_num_ordered_t const fr_tokens_table[]
Definition token.c:33
@ T_OP_SUB_EQ
Definition token.h:68
@ T_OP_EQ
Definition token.h:81
@ T_OP_SET
Definition token.h:82
@ T_OP_ADD_EQ
Definition token.h:67
int unlang_xlat_eval(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *xlat)
Evaluate a "pure" (or not impure) xlat.
Definition xlat.c:711
bool xlat_impure_func(xlat_exp_head_t const *head)
static fr_slen_t head
Definition xlat.h:420
fr_slen_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Definition xlat_expr.c:3163
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
#define fr_strerror_const(_msg)
Definition strerror.h:223
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
Definition types.c:31
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition value.c:7390
#define fr_box_strvalue_len(_val, _len)
Definition value.h:309
static size_t char ** out
Definition value.h:1030